I have for the last few month been trying to familiate myself with the mvvm pattern in wpf. This is a topic that is widely discussed and i have come across articels which in places contradict one another. I know mvvm is a pattern and not a universal truth however do in certain case find thesse grey area of deciding what goes where, and what does what. 99% of the time it is between the viewmodel and view these problem arises.
my current mindset for deciding what belongs where:
Model: it only contains data which is to be saved to a file. Nothing More, nothing less.
ViewModel: is a communication bridge between a view and one or more models associated with that view.
View: handles visual representation, visual popups and visual modifications
first of af simple question concerning the Model: (Case 1)
In every implementation i have seen so far the model object is class implementing the INotifpropertyChanged. Why should the model be a class and not just simply an interface describing what the data should be and let the viewmodel implement this interface? The model should not deal with the ui even if it is decoupled and therfore giving a model class the INotifyPropertyChanged is just as wrong as making the viewmodel inherit from a DependencyObject (even though i understand its importance in that type of model implementation)?
Grey area example of what the ViewModel should handle vs the View: (Case 2)
Say i am creating a Uml editor where there are Nodes and Connectors Created in a viewModel and kept in thier own ObservableCollection.
<SomePageView.DataContext>
<vm:SomePageViewModel/>
</SomePageView.DataContext>
<Grid>
<ItemsControl ItemsSource="{Binding Nodes}" DataTemplate="{Binding SomeNodeUserControl}"/>
<ItemsControl ItemsSource="{Binding Connectors}" DataTemplate="{Binding SomeConnectorUserControl}"/>
</Grid>
When a node is dragged around the grid any attached Connector endpoints will follow the node around as it is moved. I personally see this as Comunication between the UiElements, but there are 2 fundamentally different ways of implementing this type of behavior. Update the Connector by keeping a complete reference to the NodeviwModel and use its position members to update the position of the Connector. It is a pretty simple approach however do not like it as i believe it should be the ConnectorView that update the postion of The ConnectorVm. this requires that the Connector View know something about a specific NodeView. However this approach more complicated and i havent found a valid solution for it yet ( currently looking into the EventAgregator pattern). The Reason why i like the last aproach is that if select a connector it should be the view that dictates how the connector can be moved around and not the ViewModel. Any comments or advice on my observations?
in the mvvm pattern were should ui patterns be kept: (Case 3)
in mvvm where should the eventAgregator, Mediator be used. in the ViewModel or the CodeBehind? My current belief is they belong in the code behind, but i have a shred of uncertainty regarding this matter. If kept in the codeBehind i csn imagine a cleaner aproach by using the The VisualTree with the loadedevent instead of using constructors taking arguments of Eventagregator and likewise.
Similar i can implement an UndoRedoController which would not require to be a singleton. should be easier to test, possible to have more UndoRedoControllers existing. An example could be a document program that allow mutiple documents to opened at once in tabs and therfore should have thier own UndoController.
Case 1
In M-V-VM the ViewModel always (Model not always) implements INotifyPropertyChanged
Model can but doesn't coz you really don't want to pollute Model with a fairly WPF specific feature like INPC .
The model should not deal with the ui even if it is decoupled.
INPC interface is not UI specific! It simply informs of a change. Indeed WPF heavily uses this to identify changes, but doesn't mean it is a UI interface.
Case 2
View is responsible ideally for just the representation of data.While dragging is an action on the view,the UI/data updation in the view/ItemsControls are based on the decisions of viewmodel.
There is no harm in using the code behind if the implementation is comparatively easier and logical as in ViewModel, but if you can accomodate the same in viewmodel,you should.
Case 3
It should be in the view model.
If kept in the codeBehind i csn imagine a cleaner aproach by using the
The VisualTree with the loadedevent instead of using constructors
taking arguments of Eventagregator and likewise
Using events, will result in a tight coupling between views that makes the application harder to maintain. It could potentially also lead to memory leaks if the main class(publisher) of an event lives longer than a visual controls/usercontrols(subscribers) and you forget to, or don’t know when to, unsubscribe from an event.
Related
I'm somewhat new to MVVM but I have had my hands on it for some time now. Unfortunately, perusing the internet there seems to be no solid consensus on the best way for an application to process events in MVVM. I have a situation pictured below in which I am combining two controls - each in a self contained xml that i'm going to call two separate views: ListBox and ButtonPanel.
How should the direction of events flow then? Let's take a scenario where upon clicking my button in the button panel, a file is created in the list box control. Would the flow of events in image one or in image two be more appropriate?
Event Flow One - Communicating ViewModel to ViewModel:
Event Flow Two - All Front end classes don't communicate. All messages are passed via the Application Layer (whatever is hooked up to the back end: db, processing functions, etc..)
Please note - i didn't picture it but I am using ICommand to pass the click event from my Button Panel View to my Button Panel View Model.
And lastly once again my question is: How should events be processed in an MVVM flow. Are either of my graphics appropriate?
* **EDIT IN RESPONSE TO Ed Plunkett's ANSWER ***
Is this then the sort of event flow you would expect:
Is this closer to the correct architecture?
In this image the << >> between ViewModels are actually properties being exposed to the views, and the majority of the events are being handled as bindings there in the view.
My concerns with this are:
The Master ViewModel is now responsible for collecting information from both views. I'm not sure how to handle this without using mediator/messenger - that is without tightly coupling my parent view model to the child. Either i'd have to register events by name in all view models, or make specific callbacks by name for each of the viewmodels, so a mediator would still be necessary to achieve loosely coupled design (which is the entire advantage of using MVVM).
Even if i'm wrong in point 1 - what is the advantage of using a parent child ViewModel relationship?
Concerning the point of ViewModels don't know what a button or a panel is:
I agree. You can ignore my naming of classes here. I've just done it this way to make the question easy to understand - named classes so that an onlooker knows what control is being handled in each. My actual classes are named based on the data they handle, not the component.
Simplest case: One viewmodel.
The button invokes a command that it gets from a property of the viewmodel.
The viewmodel also has a property something like
public ObservableCollection<SomeFileViewModelClass> Files { /* INPC stuff */ }
The button has no idea what the command does. Presumably the command tells the viewmodel to create a file, and add a new instance of SomeFileViewModelClass to Files.
Meanwhile, back in the XAML, the ListBox is using Files as an items source:
<ListBox
ItemsSource="{Binding Files}"
...
...so the listbox will automatically update to show the new file.
If you want your button panel to have its own viewmodel (you almost certainly don't, and even if you do, don't call it a "button panel viewmodel"; viewmodels don't know what buttons or panels even are) and your file list to have its own viewmodel (maybe), make those kind of things child viewmodels of the main viewmodel. The main viewmodel creates them and manages relationships between them.
public FilesViewModel FileList { /* INPC stuff */ }
Maybe FileList now owns ObservableCollection<SomeFileViewModelClass> Files -- but if that's all it owns, it isn't a viewmodel. Just put that Files property on the main viewmodel.
<Button Content="Create File" Command="{Binding CreateFileCommand}" />
<!-- ... snip -->
<ListBox ItemsSource="{Binding FileList.Files}" />
Maybe CreateFileCommand should be a property of FilesViewModel, if that even exists.
Keep it as simple as possible, but no simpler.
Do not design a UI and then create one viewmodel for each thing in the UI. That's backwards. Controls don't have viewmodels.
Design viewmodels to model the things your application needs to deal with. Parent and child viewmodels, based on the actual relationships between the actual stuff (personally, I prefer to model the smallest "leaf node" things first, then work my way into the center). Then add views to display them to the user. This takes a little getting used to, but it pays off.
Your viewmodels are "The Program". You write views to display the program to the user and let the user talk to the program. You write models/database/file access/whatever to let the program store and retrieve state.
Your "All messages are passed via the Application Layer" idea is not MVVM.
Your second thing with the yellow "mediator/messenger" box is close to correct, but there's no "mediator/messenger"; parents talk to children. If a child will need to know something about a sibling, you would manage that by having the children expose events. The parent can wire up event handlers among the children -- to do it quick and dirty, you can always handle INotifyPropertyChanged.PropertyChanged on a child, but specialized events are often preferred. Dependency injection is another option but it's easy to end up writing classes with a maze of dependencies. DI can turn into an antipattern, and multi-colored block diagrams of the information flow in user interfaces is a leading indicator that it's about to.
Your case is simplified, but you'd really have a "ListBox View" that contains a ListBox and a "Button View" that contains the button. Both of those views would be child views of the "Main Window View".
I'd have to disagree with Ed here and say I would never combine VMs... that breaks the single responsibility paradigm that MVVM tries to install.
The standard MVVM way of having VMs communicate is through the messenger / event aggregator paradigm.
So i'd vote for workflow #1. ALMOST...
VM's should NOT send a message to another VM to write to a DB, etc. That's what models are for.
If you want to abstract away the DB, the standard way to do that is to define a IDataProvider type interface and use DI to inject it into VMs that need it. You'll find as your app gets larger and more complicated, DI and MVVM are a match made in heaven.
MVVM + DI + Messenger all work together beautfully and keep everything seperate and organized.
Personally I like to keep V <-> VMs 1:1 with no code behind, but that's the super purist definition of MVVM.
EDIT: Just to clarify, I don't think you really mean you are just plopping 2 controls on a form and making each a VM, I wouldn't do that. Break the UI into logical "regions" and each "region" would have a VM and a V.
I'd like your inputs on what are the main differences between a MVVM project and a MVC project. I know the basic principles of MVVM and MVC but i'd like to know more technically about their difference in a WPF project.
The most significant difference I see is the emphasis on the ability to 'switch out parts' using MVVM. The idea is that the Model doesn't know about the ModelView and similarly the ModelView doesn't know about the View. So if you completely re-design the View, the ModelView is unaffected.
With MVC it's likely that each of your inter-component references will go both ways (the Model will know about the Controller and vice versa). This helps with interoperability of components but makes it difficult for any one piece to exist independently of the other two. If you want to change your View you'll probably have to make proportional changes to the other two components.
With MVVM the model should be able to just do its thing with the data, oblivious to whether anyone outside its existence cares what it does. The ModelView should be able to leverage all the cool stuff the Model is doing and make the data consumable to outside resources, but should be otherwise oblivious about how the end user will do the consuming. Finally, the View knows about the ModelView and can get from it whatever it needs to customize the experience for its user.
The two big selling points are that you can switch out the View (nearly) seamlessly. The ModelView knows nothing of the View so it runs regardless. How the View plugs into the ModelView is entirely up to the View. The other point is that you can unit test the Model and ModelView in relative isolation. You don't need to initialize a View component to run it.
Although long and somewhat dense, this is a good read: https://msdn.microsoft.com/en-us/magazine/dd419663.aspx
The other answers here talk about some of the benefits of MVVM, but I feel they fail to answer the question. I believe you're asking a philosophical question about the difference between MVC and MVVM.
In my experience, the Controller in MVC is responsible for triggering state changes on the View and Model. For example, your View might have a function like this:
public void SetupListBox(List<string> items) {...}
Or something even more monolithic, where lots of bits of information are provided at once:
public void SetupForm(string name, List<string> listItems, string selectedItem) {...}
The Controller will explicitly call this type of method to trigger the state change, and the View (in this case) will change its state within the method.
With MVVM, the ViewModel publicly exposes the state of the view, usually at a granular level:
public string Name { get {...} set {...} }
public List<string> ListItems { get {...} set {...} }
public string SelectedItem { get {...} set {...} }
The ViewModel also is responsible for notifying the View that a relevant state change has occurred. WPF uses INotifyPropertyChanged for this.
One way to think about it is that the ViewModel abstractly represents the state that SHOULD be present in the View. Whether that state is actually reflected in the view depends on how well you've implemented your architecture.
Note that MVC and MVVM are not competing patterns. With MVVM, you still need logic to drive the state changes. The key difference is where that state lives. It's often easiest to put all that state change driving logic directly in the ViewModel. Larger applications may require an MVVMC architecture.
Both of them are architectural patterns, the older is MVC, then comes MVP (Model View Presenter) and from MVP inherits MVVM.
If you implement MVVM in your WPF app, your code should be more decoupled because the view-logic should be implemented in a viewmodel class that can be rehused because is independent of the view. Thanks to the capabilities of WPF you can control your view's behavior through your viewmodels, where you expose observable data that can notify to the view when something has changed (but the viewmodel doesn't know what is the data source), and commands where you implement the actions that tell the view what to do in response of user interactions (but the viewmodel doesn't know nothing about the view).
In other types of app like Asp.Net Web Forms or Windows Forms, the only way how we achieve this is writing the "code behind", where we control the users interactions and put the presentation logic, this is normally using MVP and MVC, in this way you have more code that depends of the UI and a simple UI change can break more code.
I've been working with WPF and MVVM a lot lately. I was under the impression that I understood the MVVM pattern quite well but I've begun having some doubts.
Right now, I have an encapsulating ViewModel object for each Model object.
Let's say my Model contains two classes: Property, which contains a list of PropertyValue. In my ViewModel, I have a PropertyVm, which contains a Property and a list of PropertyValueVm (each containing a PropertyValue). Both Vm's implement a BaseVm which contains the OnPropertyChanged method.
Consider a View with two comboboxes, for Property and PropertyValue. The first combobox's ItemsSource will be bound to a collection of PropertyVms and the second combobox's ItemsSource will be bound to the PropertyValueVms of the PropertyVm selected in combobox 1.
This is all based on the article that got me to explore WPF and MVVM in the first place: Simplifying the WPF TreeView by Using the ViewModel Pattern, by Josh Smith
However, I'm becoming increasingly annoyed with the large amount of ViewModel classes my project contains, some of which contain very little code or simply nothing but the corresponding Model class.
Other implementations I've come across have the INotifyPropertyChanged on the Model objects instead. This would mean you'd assign the Model objects to the Comboboxes directly. This would slim down the amount of ViewModel classes, but doesn't this violate the basics of MVVM?
I've also seen people advocating a single ViewModel per View. But I fear this would turn my ViewModel classes into humongous, incoherent walls of texts.
So my question in short: Should I have an encapsulating ViewModel for each Model? If not, then what is best practice?
The primary driver of MVVM is to maximise the testable code via the strong separation of presentation and presentation logic. Ideally we encapsulate the presentation logic in one or more view models - so in terms of your sub-question, have as many view models as makes sense. Dividing the functionality up into a series of smaller view models is good practice from my experience. But there is no one-size-fits-all way to implement this. So in some ways, the answer to the question is: it depends on your situation.
If your model never changes then you've reached a religious fork in the road. The pragmatist exposes the model to UI binding (guilty!!). The purist wraps the model in a view model because the VM sits between M and V in the design and if we don't dogmatically adhere to this then bad things must surely happen.
If your model changes then you have design choices. You can keep the model immutable and refresh your view model with a new version of the model and raise changes from there. Or, if your architecture facilitates an ever updating model that the UI just needs to represent then ask yourself if you truly gain by sticking a view model in the middle. But!! As soon as you get a sniff of logic creeping into the model then it's worth a view model.
Should I always use Command even though it might not be necessary?
Or should I only use Command in the case where more things, menu items, buttons,
whatever, when clicked execute the same code?
Maybe it is good practice to always use Command, or maybe it adds additional
unnecessary complexity. I am new to WPF so please share some advices.
If you're using the MVVM pattern, which is mandatory in every serious WPF application, 'ICommand' is the way to go for every action that is not purely interface logic.
I'll explain:
As you probably know, the MVVM pattern distinguishes between Model, ViewModel and View, where the ViewModel mediates between Model and View. The ViewModel usually holds all the data which is consumed by the view and which you bind your view to. The important thing is:
The View is agnostic of the ViewModel
This means, although your View is bound to the ViewModel, it doesn't reference it, there is no logical dependency to the ViewModel. The 'ICommand' bridges this gap: It kind of packs an action into a bindable property. That's the main point, probably:
A command wraps up an action or function into a WPF databindable
property
And as databinding is the mechanism which, in MVVM, View and ViewModel are connected with each other, the command is the vehicle to perform every action, no matter if it is triggered by one control or by many, that transcends the sphere of pure UI (which is almost everything):
Have a look here (MSDN), where this image is taken from:
If you don't use MVVM I'm not sure whether you need commands at all. There is no significant difference to WinForms then, regarding the UI event handling. But again: MVVM and WPF go hand in hand, in my opinion.
I have a a user control which contains several other user controls. I am using MVVM. Each user control has a corresponding VM. How do these user controls send information to each other? I want to avoid writing any code in the xaml code behind. Particularly I am interested in how the controls (inside the main user control) will talk to each other and how will they talk to the container user control.
EDIT:
I know that using events-delegates will help me solve this issue. But, I want to avoid writing any code in xaml code-behind.
Typically, it's best to try to reduce the amount of communication between parts, as each time two user controls "talk" to each other, you're introducing a dependency between them.
That being said, there are a couple of things to consider:
UserControls can always "talk" to their containing control via exposing properties and using DataBinding. This is very nice, since it preserves the MVVM style in all aspects.
The containing control can use properties to "link" two properties on two user controls together, again, preserving clean boundaries
If you do need to have more explicit communication, there are two main approachs.
Implement a service common to both elements, and use Dependency Injection to provide the implementation at runtime. This lets the controls talk to the service, which can in turn, keep the controls synchronized, but also keeps the dependency to a minimum.
Use some form of messaging to pass messages between controls. Many MVVM frameworks take this approach, as it decouples sending the message from receiving the message, again, keeping the dependencies to a minimum.
Your conceptual problem is here:
Each user control has a corresponding VM.
Having a separate ViewModel for every view pretty much defeats the concept of a ViewModel. ViewModels should not be one-to-one with views, otherwise they are nothing but glorified code-behind.
A ViewModel captures the concept of "current user interface state" -- such as what page you are on and whether or not you are editing -- as opposed to "current data values'.
To really reap the benefits of M-V-VM, determine the number of ViewModel classes used based on distinct items that need state. For example, if you have a list of items each of which can be displayed in 3 states, you need one VM per item. Contrarily, if you have three views all of which display data in 3 different ways depending on a common setting, the common setting should be captured in a single VM.
Once you have strucutred your ViewModels to reflect the requirements of the task at hand you generally find there is no need nor desire to communicate state between views. If there is such a need, the best thing to do is to re-evaluate your ViewModel design to see if a shared ViewModel could benefit from a small amount of additional state information.
There will be times when the complexity of the application dictates the use of several ViewModels for the same model object. In this case the ViewModels can keep references to a common state object.
There are many differenct mechanisms for this, but you should first find out in what layer of your architecture this communication belongs.
One of the purposes of the MVVM framework is that different views can be made over the same viewmodel. Would those usercontrols talk to each other only in the view you are currently implementing, or would they have to talk to each other in other possible views? In the latter case, you want to implement it below the view level, either in the viewmodel or the model itself.
An example of the first case may be if your application is running on a very small display surface. Maybe your user controls have to compete for visual space. If the user clicks one usercontrol to maximize, the others must minimize. This would have nothing to do with the viewmodel, it's just an adaption to the technology.
Or maybe you have different viewmodels with different usercontrols, where things can happen without changing the model. An example of this could be navigation. You have a list of something, and a details pane with fields and command buttons that are connected to the selected item in the list. You may want to unit test the logic of which buttons are enabled for which items. The model isn't concerned with which item you're looking at, only when button commands are pressed, or fields are changed.
The need for this communication may even be in the model itself. Maybe you have denormalized data that are updated because other data are changed. Then the various viewmodels that are in action must change because of ripples of changes in the model.
So, to sum up: "It depends...."
I think the best solution would be using Publisher/Subscriber pattern. Each control registers some events and attaches delegetes to events exposed by other controls.
In order to expose events and attach to them you would need to use some kind of Mediator/EventBroker service. I found a good example here
The best way to do this in my opinion is via Commanding (Routed Commands / RelayCommand, etc).
I want to avoid writing any code in the xaml code behind.
While this is a laudable goal, you have to apply a bit of practicality to this, it shouldn't be applied 100% as a "thou shalt not" type of rule.
You can communicate between elements on the UI by using element binding, so assuming a user control you created exposes a property, the other user controls could bind to it. You can configure the binding, use dependency properties instead of basic properties / implement INotifyPropertyChanged but it is in theory possible, but does require some forethought to enable to communication this way.
You will probably find it far easier using a combination of events, code and properties than try a pure declarative way, but in theory possible.
You can share some View Model objects between controls as well as Commands...
For example, you have some main control, which contains two other controls. And you have some filtering functionality in the main control, but you want to allow user to set some part of the filter in the first sub-control (like "Full filter") and some part of the filter in another (like "Quick filter"). Also you want to be able to start filtering from any of sub-controls. Then you could use code like this:
public class MainControlViewModel : ObservableObject
{
public FirstControlViewModel firstControlViewModel;
public SecondControlViewModel firstControlViewModel;
public ICommand FilterCommand;
public FilterSettings FilterSettings;
public MainControlViewModel()
{
//...
this.firstControlViewModel = new FirstControlViewModel(this.FilterSettings, this.FilterCommand);
this.secondControlViewModel = new SecondControlViewModel(this.FilterSettings, this.FilterCommand);
}
}
public class FirstControlViewModel : ObservableObject
{
//...
}
public class SecondControlViewModel : ObservableObject
{
//...
}
In the main control XAML you will bind sub-controls DataContext to the appropriate View Models. Whenever a sub-control changes filter setting or executes a command other sub-control will be notified.
As others have said you have a couple of options.
Exposing DepedencyProperties on your user controls and binding to those properties provides a pure XAML solution in most cases but can introduce some UI dependencies in order for the bindings to see each other
The other option is a decoupled messaging pattern to send messages between ViewModels. I would have your user controls bind to properties on thier own VM's and then on the property change inside that VM it can "publish" a message that notifies other "subscribers" that something has happened and they can react to that message however they want to.
I have a blog post on this very topic if it helps: http://www.bradcunningham.net/2009/11/decoupled-viewmodel-messaging-part-1.html
If you're using strict MVVM, then the user-control is a View and should only "talk", or rather, bind, to its ViewModel. Since your ViewModels most likely already implement INotifyPropertyChanged, as long as they have a reference to each other, they can use the PropertyChanged events to be notified when properties change, or they can call methods (better if it's through an interface) to communicate with each other.