Common abbreviations: M-V-VM or MVVM
Separating user interface code from everything else is a key principle in well-engineered software. But it’s not always easy to follow and it leads to more abstraction in an application that is hard to understand. Quite a lot design patterns try to target this scenario: MVC, MVP, Supervising Controller, Passive View, PresentationModel, Model-View-ViewModel, etc. The reason for this variety of patterns is that this problem domain is too big to be solved by one generic solution. However, each UI Framework has its own unique characteristics and so they work better with some patterns than with others.
The WPF Application Framework (WAF) provides support for the Model-View-ViewModel Pattern because this one works best with Windows Presentation Foundation (WPF) applications. This pattern is also known as PresentationModel pattern.MSDN: A variant of the Presentation Model pattern named Model-View-ViewModel is commonly used in Windows Presentation Foundation applications.
Represent the state and behavior of the presentation independently of the GUI controls used in the interface.
A popular description of this design pattern is done by Martin Fowler. In his article the pattern is called PresentationModel but it is the same pattern. You can read his article online on his website
. The following chapters describe our specific .NET implementation of this design pattern.
The following UML class diagram shows the collaborating classes of this design pattern in a logical layered architecture.Figure 1: The structure of the Model-View-ViewModel Pattern
The types participating in this pattern are:
- View contains the specific GUI controls and defines the appearance of the user interface.
- IView declares the interface of the View. The ViewModel can communicate over this interface with the View. Related pattern: Separated Interface (PoEA).
- ViewModel represents the state and behavior of the presentation.
- Model can be a business object from the domain layer or a service which provides the necessary data.
- Controller is responsible for the workflow of the application. Furthermore, it mediates between the ViewModels. So it promotes loose coupling by keeping the ViewModels from referring to each other explicitly. Related patterns: Application Controller (PoEA), Mediator (GoF)
- The introduction of the interface IView is a variation of the Model-View-ViewModel pattern. It allows the ViewModel to call properties and methods on the View.
- The Controller class is not part of this design pattern. The controller is supported by the WPF Application Framework (WAF) and so this article shows how the controller works together with the M-V-VM pattern.
- The View can call operations on the ViewModel directly. The ViewModel needs to communicate through the IView interface when it has to update the view.
- The View can collaborate with the Model but it should restrict this on simple data binding. It’s recommended to handle more complex operations by the ViewModel.
- The upward communication from the Model to the View or to the ViewModel can be done through events. A common solution is to raise property changed events on the Model. This way the View can use WPF data binding to synchronize the data between the Model and the View. Related pattern: Observer (GoF).
- The Controller can call operations on the ViewModel directly, whereas the backward communication from the ViewModel to the Controller might be done through events. Related pattern: Observer (GoF).
This specific implementation of the ViewModel pattern has the following liabilities:
- The ViewModel is dependent on a specific GUI framework. We use the commanding and the weak event concept of WPF.
- The ViewModel might listen to events (e.g. PropertyChanged events) of the Model. In such a scenario you have to keep the lifecycle of the ViewModel and the Model in mind. When the Model lives longer as the ViewModel it is essential to unwire the event or to use weak events so that the garbage collector is able to remove the ViewModel instance. The WPF Application Framework (WAF) supports weak events with the ViewModel base class.
The WPF Application Framework (WAF) provides some types which helps you to implement this pattern.
Derive your ViewModel implementation from this class. The ViewModel class provides a default implementation of a weak event listener and it is responsible that the DataContext of the WPF view gets the instance of your ViewModel.
All WPF views that are managed by a ViewModel have to implement this interface. You can create your own interface for exposing properties and methods of the View.
This class provides a simple implementation for the ICommand interface. The constructor requires a delegate which is called when the command is executed. A second delegate can be passed to the constructor which is called when the command needs to refresh its state. With the second delegate it is possible to enable or disable the command. The command state refresh is triggered through the RaiseCanExecuteChanged method.
This command implementation is an ideal candidate for the ViewModel class. By using the DelegateCommand, the ViewModel gets informed when it should handle a user interface action (e.g. Button was clicked). You need to expose the commands in the ViewModel through properties and bind on them in the View.