If the code-behind for the View is meant to consist of nothing but the constructor with the InitializeComponent() call, why not just use DataContext="{Binding RelativeSource={RelativeSource Self}}" and use the view itself as a view model?
I get that this technically violates the Single Responsibility Principle, but since the XAML and code-behind are defined independently from each other, it doesn't cause the usual mess. Having separate view models for everything causes more mess to the file structure.
ViewModel describes view state. For testing and reusing purposes it must be UI independent.
Benefits:
You can cover ViewModel by unit tests and you haven't to refer UI
classes in test
You can reuse your ViewModel on other UI targets:
console app, WinForms App, UWP app, Xamarin iOS/Android App, no
display IoT project. You'll need to write only view for new target platform.
Sometimes even in WPF and MVVM you have to write some code behind for View-only purpose because it may be much more simpler, readable and reliable then create some new entity for that. And you'll get mess if you have also ViewModel in code behind.
Related
I've been dabbling with MVVM. In fact, I've religiously tried to follow it's rules and best practices.
How is program initialization handled properly?
Specifically, I am confused as to why you would call the view (from the App.xaml) first.
My assumptions has been, that a controller still owns the abstraction of the view (ViewModel) and uses it to update the view. (I prefer to separate presentation and processing into different classes, which I guess would make this "MVVMC").
So in my eyes, the view should not be the first thing to be initialized.
This being said, my solution has been to start the controller from the app.xaml code-behind and pass the ViewModel to the controller.
Even though I get a nice information pipline, I have the feeling that this is not the correct way, since I am still using the app.xaml code-behind.
This is what my application looks like:
So, what is the best/most-efficient/most-accepted way to initialize an application?
First of all, MVVM isn't a very strict ruleset and it definitely leaves space for a wide variety of flavors.
Based on whether View or ViewModel is instantiated first, you can differenciate two aproaches:
ViewModel first approach, where instance of ViewModel is created first and then typically based on some convention a View is selected. DataTemplateSelector is a good example.
View first approach, where view is created first (typically a Window or UserControl) and using some convention view is selected. It might be a responsibility of a View to create a ViewModel instance for itself, or it might be delegated to somebody else.
When it comes to initialization, it must always be done in app.xaml resp app.xaml.cs as it is the entry point for your app. You also must realize, the application process is
bound to the Dispatcher loop. When the last Window in your app is closed, dispatcher loops ends and the application process exits. The last window is typically the MainWindow.
Also, take the application startup time into account. You want to display some Window as soon as possible. So if you want to do any logic before the Window is shows, make sure you don't do any I/O, database or API calls, etc.
I typically have Bootstrapper.cs class that I invoke from App.xaml.cs. It's responsibility is to setup IoC and display the UI. It might be a loading window and then MainWindow.
In Bootstrapper.cs you might create instance of MainWindowViewModel first, the create MainWindow and assign the ViewModel to it's DataContext, or you might just create MainWindow and leave the ViewModel creation up to the MainWindow itself. I tend to do the latter.
There is nothing wrong with either of the approaches and neither violates the MVVM principle.
My biggest recommendation to you is - if you can't decide between two or more options, choose the simpler. Or in other words, don't complicate things unless you have very good reason to. KISS
I have some doubts in viewmodel pattern. My doubt is about, why we don't use UI elements in viewmodel. If we use UI elements in viewmodel what will happen like any performance issue?. Please give any suggestion.
You do not use UIElements in ViewModels, since the MVVM principle defines UIElements to reside in the View. The correct placement of UIElements, is defined by John Gossman, in the article Introduction to Model/View/ViewModel pattern for building WPF apps:
The View in Model/View/ViewModel consists of the visual elements, the buttons, windows, graphics and more complex controls of a GUI.
You do not use UIElements in the ViewModel of an MVVM application, for at least two reasons:
When later porting the application to another UI framework, it is much easier if all UI related code is just in one module, namely the View. Porting would be much harder if UI code would be spread across the View and the ViewModel.
Unit testing is much easier if all UI related code is just in the View.
The latter reason, of course, is the most important, for most developers. Josh Smith, the father of WPF-MVVM puts it like this in his article Patterns - WPF Apps With The Model-View-ViewModel Design Pattern:
If you can write unit tests for the ViewModel without creating any UI objects, you can also completely skin the ViewModel because it has no dependencies on specific visual elements.
UIElements are troublesome for unit tests, because WPF UIElements need a layout-measure-render loop for working correctly. In unit tests, however, you usually do not have such a loop.
I'm trying to learn the MVVM model by creating an UWP project. From what I've gathered, ViewModel is supposed to be independent from the actual View (portable?). I just want to clarify if what I understand is right.
Say I have a SplitView:
<Grid>
...
<Button Click="ActivateRelativePanel Content="CLICK!"/>
<SplitView>
<SplitView.Pane>
...
</SplitView.Pane>
<SplitView.Content>
<Frame Name="MyFrame"/>
</SplitView.Content>
</SplitView>
</Grid>
Is it right to change the Open/Closed status (SandwitchSplitMenu.IsPaneOpen = !SandwitchSplitMenu.IsPaneOpen;) of the SplitView in VM or xaml.cs, since this is a view specific thing? From what I understand so far, this should be inside a xaml.cs file, since it's a view specific thing, but a friend of mine told me that I should use xaml.cs file as less as possible when relying on MVVM.
While I'm at it, should the Frame be Navigated (MyFrame.Navigate(typeof(SomePage));) through the VM or xaml.cs? The frame is also a view-specific thing.
I know that loaded data from the models should be done by binding, through VM, but I'm interested as to what is supposed to be inside a VM and what is supposed to be inside a xaml.cs file.
Also, any other good UWP MVVM tutorial guide or anything is more than welcome!
Well, several things:
MVVM pattern lets you decouple your view and your business logic. There's many advantages, and one of them is testing. You can test your view model without thinking of your view because it is made to be independent (your view model does not have any consciousness of a view). Separation of concerns is also a great practice to get your code organized.
Starting from this, you should place in your code-behind the minimum code possible. Acceptable code would be code which manipulates UI element exclusively, like sizing, managing animations, ... All which is related to data and other stuff should go directly into your view model.
Navigation should also be handled from view models, because logic takes place there, and navigation relies on logic.
For your IsOpenPane case, it's subject to debate. It manipulates the UI element but I suspect it's manipulated from a business logic. So, personally, I would declare a public property in your view model which you bind to the xaml property IsPaneOpen.
Regarding UWP MVVM guide, you should see MVVM: Tutorial from start to finish?.
It is not exclusively for UWP and resources are quite old, but the concepts are the same (only some XAML elements are differents, but pattern and spirit are exactly the same).
But above all: https://mva.microsoft.com/search/SearchResults.aspx?q=uwp
Microsoft MVA is really great!
Once you'll be at ease with XAML and MVVM, see https://dev.windows.com/en-us/design. It's the official Microsoft documentation about UWP and design, where you can grasp key concepts like responsive design techniques (which is specific to UWP, and brings tools which make a universal app usable by any display, from IoT to TV). It's of course well written and well structured.
I'm using PRISM and MVVM in my modular Silverlight application. I'm still trying to figure out PROPER way to do interactions in MVVM fashion and 2 methods that PRISM and samples offer is not something I like for different reasons.
Method 1(PRISM): To use different region adapter. Basically, it involves attached properties on container and injecting view into region. This works almost 100% but negative of this method is that there is no good way to communicate results back. I can use EventAggregator but something doesn't feel right to raise event with data when interaction completed.
Method 2(PRISM): To use InteractionRequest. That involves trigger action and some big boilerplate XAML that I have to repeat on each view.
I'm thinking on creating something on my own which would require creating my own control which will have to be added to each view but with very little XAML and some kind of IPopupService that I can bind this control to. I can pass all needed data via PopupService but in order to actually make action of POPUP happen - I need to call method on this control and that falls apart in MVVM
I wonder how to call method on control in MVVM where view shouldn't be aware of VM ?
View has no option but be aware of VM, since it binds to it.
You could define some kind of a service indeed with a run-time implementation that would interact with the UI and design/test/debug implementation that does something else. You might also publish some events in your VM layer that the View layer would decide how to interpret.
First off, I don't think MVVM is a good choice if you are developing a UserControl that will be consumed by others. A lookless control is what you really should be developing. Jeremiah Morrill has a blog post about this subject.
With that said, you can set the datacontext with XAML if you have a default public constructor.
Inside ControlView.xaml put:
<UserControl.DataContext>
<local:ControlViewModel />
</UserControl.DataContext>
Recently i got explained that MVVM can only be done "the right way" if i use DataTemplates. Is this truely the case?
I'd say its a good idea to use DataTemplates if you want highly reusable "Views".
But if i am going to develop an application that has, say, five to ten different pages, and there is very little to none reuse of specific controls (like the "Person" view is only used once, and its highly likely that this requirement doenst change), why cant i simply create a usercontrol and put that directly into the code?
Am i missing some important core principle of MVVM here?
Main selling point of MVVM is separation of View from the ViewModel (so that VM doesnt know about View) by using powerful Binding feature of WPF.
DataTemplates are a just another feature which allows you to represent data in different way. As you have said, if you dont have reusable DataTemplate then dont create one, even if you do make sure it resides in the View's Resources, you can share it wider group if you wanted do.
using UserControl can be useful where you need to do something extra (apart from simple representing data), for example, some complex validation or extra commands/buttons
I dont think MVVM and DataTemplates are related in the same context.
There is no special needing for DataTemplate, you have a view and a viewmodel that cooperates with databindings and events. The MVVM goal in WPF is to remove the code from the view to achieve a real presentation only view, and not a messy code behind store. Having the ViewModel agnostic from the view is another goal, even if not always achieved.