Comments (27)
Actually, in Prism 6 IView is gone. There will be no need for it. As far as using x:Bind, you simply need to add a strongly typed property to your View code behind and use x:Bind against that.
public MyVieModel ViewModel
{ get { return (MyViewModel)DataContext;} }
from prism.
While x:Bind brings a nice performance boost, it sadly breaks the separation between view and view model that MVVM brings. Not sure if we should add code to enable this scenario.
The strongly typed property is indeed the easiest way to make it work. We could add a code snippet to the prism releases to help users create the necessary property.
from prism.
public MyVieModel ViewModel
{ get { return (MyViewModel)DataContext;} }
Yuck. π (Not you, Brian, just the nature of the matter.)
While x:Bind brings a nice performance boost, it sadly breaks the separation between view and view model that MVVM brings. Not sure if we should add code to enable this scenario.
I agree. What is going on over there in the UWP group? I am not sure if you saw this, but they actually admitted during this Channel9 session that they were considering removing Bindings from Xaml altogether as an actual legitimate solution before landing on their "new and improved" x:Bind. Even after all this time, they still don't have markup extensions (or about 80% of what makes Xaml so awesome). As you (sort of π) allude to, Bart... does anyone in that group know (or care) what MVVM is or are they just making it up as they go along? The whole WinRT/Windows Store platform feels hijacked compared to WPF/Silverlight. That's exactly the word it feels... hijacked, and by all the wrong engineers. Right down to that blasted Curtain of COM that hides all the particulars so you can see what is really going on in the application.
(Sorry. Just had to rant a bit. It's been a while! Haha.)
Terrible. Just terrible. And frustrating. Is it too late to start (another) Silverlight6 petition? Doh.
from prism.
Duck typing (i.e. current Bindings) isn't separation though - it's just obfuscation. If you change the underlying type, it still breaks if it doesn't match the implicit interface. If you bind x:Bind to an interface instead of a concrete type, you've maintained the dependency inversion principle, and removed the obfuscation. It doesn't really affect MVVM because MVVM just describes the relationship between the objects, not how they're connected. And it adheres to SOLID principles better.
But I definitely agree that wrapping the DataContext in the property seems like a hack because you are losing and then trying to regain type information. I mean it's true that most of the time I'm sure it's probably fine - as long as you set that DataContext prior to the Bindings being loaded. (Which, presumably, Prism will do.) But losing that type info by passing through DataContext does feel wrong.
But I mean, it's a wrongness I can accept for now at least haha.
from prism.
Does it work property with interfaces? Off the tope of my head, we may be able to look into an IView[T] with a definition like this:
public T ViewModel {...}
This would be a UWP thing only and not included in the other platforms for obvious reasons. Of course this would be optional, but I am not really sure exactly what this would be buying you since you are basically still having to create a property in the code-behind. So I'm not really seeing the benefit off the top of my head.
from prism.
Yeah x:Bind doesn't care what the target is, it's just strongly typed.
Your right in that we'd have to make a property no matter what, my only concern was that losing typing through DataContext feels bad.
Like, for proper injection, you need some place to put the properly typed object. Usually this is done through the constructor, but we can't cuz of the framework. The backup injection site is usually some kind of property. But if you're not planning on changing the ViewModel injection, I mean, I guess it's probably not worth it.
But yeah, IView with a IMyViewModel ViewModel {get; set;} feels a lot better than (IMyViewModel)DataContext, to me. But yeah that could be more trouble than it's worth.
from prism.
Well, I don't see an issue adding an IView for x:Bind support. The VML can look for that interface, and if it finds it then use it, if not, then just set the data context. Though, maybe we should think of a better name for the interface to make it more explicit on what the interface is used for. IBindable?
from prism.
x:Bind works perfectly with interfaces. But then we're talking off a IMyViewModel, as the properties you're binding on have to be present on the interface since this checking is done at compile time.
If you're using IView to get the type of the viewmodel into the backing property, there's no real need to use an interface for the viewmodel.
If we plan to somehow support it (and not leave the developer to think it out), then it comes down to how will we support it: provide a code snippet, provide a project item template for the view with the field, ... (alternatives?)
On a sidenote: @Michael-DST it's been long known that the WinRT/UWP team isn't providing us with a go-to example for decent MVVM. Just check how they implemented a 'viewmodel' in the Win8 templates π .
from prism.
@brianlagunas IBindable is usually used for binding targets, like ViewModels and Models, isn't it? IBindableView? IContextualView? IInjectableView? Ooh I kind of like that one.
@bartlannoeye Well, when it comes to "do you want the error at runtime" vs "do you want the error at compile time" I vote for compile time every day of the week, and twice on Sunday. I mean, yes, you can't just assign any old object and hope it all works out, but I consider this a feature, myself haha. But I tend to only connect things via interfaces to keep dependency inversion, and to allow for better testing. Usually. With Views, yeah I getcha, there's not a lot of reason to keep it separate from the view model haha.
But if you just provide the interface, I mean that pretty much does the rest. If you have a IInjectableView, then when they take the interface, and implement it with the default, it should produce TViewModel ViewModel {get; set;} right?
from prism.
Exactly, just wanted to make sure we're all on the same page here, no matter how we try to solve it, the type in the property has to be the actual view model or it's exact interface (and not a generic base type/interface).
from prism.
Well this is good timing for this discussion since I am just now starting to look at UWP support, and ViewModelLocator will be the first thing that will be brought over. A better interface name will definitely need to be thought of. ISupportXBind?
from prism.
I don't see what us adding an interface is going to buy. If you want to use x:Bind, you have to give up some decoupling and expose a property that is your ViewModel type from your code behind. Done in one line of code. What does adding an interface help with other than adding unnecessary complexity?
from prism.
The interface is about eliminating the loss of type information that happens when you inject a ViewModel into the DataContext, especially given x:Bind no longer tolerates this loss.
As I said earlier, it's true that a large majority of the time, this won't have adverse consequences. But for some devs like @Michael-DST above and myself, a hard cast of (ViewModel)DataContext is seen as - well distasteful is perhaps the best word - because it makes run-time assumptions.
from prism.
@brianlagunas Just a personal preference, but I like names that describe what the thing is meant to be, rather than why it's meant to be ... hrm ... the interface describes a View that can have a ViewModel injected in it directly. IViewModelDependent? I like how this one describes the Type you're probably going to be giving to it, i.e. IViewModelDependent tells you that T is a view model. IDependentView?
Names are hard haha.
from prism.
I am thinking something more along the lines of IXBindViewModel. I like things that are self-describing in what they are used for. I'm still not 100% sold on this, but this is something I will play around with as it is not difficult to implement.
from prism.
Names are hard haha.
Yes they are. Just ask PrismEvent, erm PubSubEvent. π
I don't have an easy answer here either, but I do like the paths of @apollyonbob's suggestions. I would like to point out that at the end of the day, "x" is merely a prefix for a namespace. It is entirely possible that some developers might choose to use another prefix altogether for that namespace, assuming that the fine folks in the UWP group allow their "Xaml" parser to account for such creative freedom (sigh).
How about IHaveAViewModel? I kid I kid...
from prism.
Actually after thinking about it, I'm not sure this would work anyways. I couldn't use a generic interface, because I would need to be able to cast the View as a generic interface, but I couldn't because the ViewModelLocator doesn't have access to those types.
I would nee to be able to do something like:
var bindable = view as IXBindViewModel;
....
Of course reflection could be used, but then we are adding a performance hit for the sake of a single property.
from prism.
Oh yeah, that was why I was thinking it might be not worth the effort. I'm using an IOC container as a ServiceLocator to get the ViewModel from just the Type, so I only need to get the TypeInfo, and it only happens 6 times in the lifetime of the app so I think the perf hit isn't too bad. But I don't know what you're doing in your framework obv, haha, or if you can even do that.
from prism.
Actually, it doesn't have to do with using a container, it has to do with trying to cast a DependencyObject (the view) as a generic interface in order to set the generic ViewModel property.
from prism.
I tried to use a Generic Base View so that I can pass the type (or better, interface) of the VM it has to work with, so that it can expose a typed property to be used with x:Bind.
However, when trying to create an instance of the View, specifying x:TypeArguments as the VM interface, it doesn't build, and it complains that I must pass a generic parameter. And in the generated class created from the XAML, it really doesn't use the generic parameter I passed.
Has anyone tried to create a generic view in UWP? Am I missing something?
Awesome work, by the way. Just love Prism.
from prism.
I do not believe this is possible in UWP.
from prism.
Have you tried having a non-generic base class that looks like this:
public class ViewBase : Page { public IViewModel ViewModel { get { return (IViewModel)DataContext; } } }
from prism.
@TioLuiso Another alternative - the solution that I ultimately went with - was to have my views implement a generic interface, IViewModelDependent<T>. (Having a single property, T ViewModel {get;set;})Then when my navigation service is first created, it gets the generic property from that interface from the View. Afterward, when someone navigates to that View, it can set the ViewModel to that property. So per page, I've got 1 GetTypeInfo, 1 GetRunTimeProperty and no magic strings. And when they actually navigate I'm just calling Property.SetValue.
But my navigation service is a set of commands, so all the View Type information is known ahead of time. Despite the little bit of reflection, I'm still not certain I'd want to do any of it during a Navigation call. Because of the way I've set it up, I can do it all during app load.
from prism.
The best extension point to hook into with Prism would be the ViewModelLocator. Create your own ViewModelLocator attached property based off of Prism's implementation:
You can see how the DataContext is being set in the Bind method. Just modify the Bind method to check for your custom interface and set it accordingly.
from prism.
Wow. Really impressive. 5 answers in 2 hours!!!
Ok @brianlagunas (Regarding the generic view) Yup. Have walked that same road. And We both found out that it didn't work.
Regarding the non-generic base page: yup. It would work. However, I was trying to find some more general solution to the problem, instead of having to update just every view code behind.
@apollyonbob yup, I guess it would work, I'll take a look. Thanks a huge lot
And after all, if it doesn't prove to be a benefit big enough, I always have dynamic bindings.
from prism.
@apollyonbob yup. It Works. Now I'll take measurements of performance, and can take a decisiΓ³n. Thanks again!!!
from prism.
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
from prism.
Related Issues (20)
- [BUG] Expected Navigation Failed. No Root Window has been created. HOT 1
- [BUG][MAUI] EventToCommandBehavior with RelativeSource binding throws InvalidOperationException HOT 4
- [BUG] Content of a ContentPage doesn't occupy full height when page is pushed to PrismNavigationPage HOT 4
- [BUG] When using iOS ModalPresentationStyles that can be automatically dismissed, navigation service gets out of sync & stops working with NavigationPage HOT 2
- [BUG] Unable to unregister the service using the Prism.Maui HOT 1
- No Root Window has been created HOT 1
- [Feature Request] Add support Keyed Service for IServiceCollection HOT 2
- Resolving with Unity works, not with DryIoc HOT 3
- [Enhancement] GetNavigationUriPath For Maui HOT 3
- [BUG] Android "hardware" back button closes the app when app contains a tabbed page with a navigation page as root page for one of the tabs HOT 1
- [BUG] Getting exception while navigating in Release mode on iOS HOT 19
- [BUG] [Android] Open app from url scheme crashes app HOT 3
- [BUG] Navigation Title view is not getting displayed on IOS HOT 2
- [BUG] Navigation Title view is not getting displayed with .net 8.0 on Andriord and IOS HOT 4
- [BUG] BindingContext cleared when performing absolute navigation HOT 3
- [Enhancement] NavigateFrom
- [Enhancement] Add ability to switch tabs and navigate
- [BUG] Android "hardware" back button closes the app when app contains a tabbed page with a navigation page as root page for one of the tabs, Take 2 HOT 4
- [BUG] Popup Dialogs are hidden/covered by calling Page when called after returning from MAUI FilePicker HOT 2
- [BUG] Link to Prism License T&C is wrong HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. πππ
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from prism.