MVVM is a central concept in WPF, Silverlight, WindowsPhone and Windows 8 development, so I decided to take some time and bubble up some of the content in the WPF MVVM Toolkit, which we created some time ago.
Model-View separation is by no means a novel idea in the software engineering industry—the idea has been around for at least 25 years. In the past few years, there has been a lot of interest in model-view architectures, fuelled both by the growing complexity of modern software systems and by the necessity to display UI on various devices, while reusing the same underlying business logic.
This post outlines the benefits of model-view separation. It is essentially the same content as the content included in Part 1 of the documentation, which goes with the WPF MVVM Toolkit.
1. Introduction to the Model-View-X Paradigm
A well-designed application is an application that is easy to develop, test, maintain, and evolve. Creating such an application typically involves some form of separation and encapsulation of responsibilities. A common approach involves separation of the UI (the views) from the business logic (the model). In fact, that approach is so common that there are a number of stock solutions, collectively known as the model-view design patterns:
- Model-View-Controller (MVC) is the granddaddy of them all, dating back to 1979. In MVC, the Controller creates the Views and the Model. The Views register with the Controller, which also has a reference to the Model. A View notifies the Controller of user interactions, and the Controller in turn queries the View for its state and updates the Model appropriately. The Controller notifies the Views when there are changes in the Model, and the Views query the controller to update their states.
- Model-View-ViewModel (MVVM) is a derivative of MVC that takes advantage of particular strengths of the Windows Presentation Foundation (WPF) architecture to separate the Model and the View by introducing an abstract layer between them: a “Model of the View,” or ViewModel. The pattern was first introduced by John Gossman – the architect on the Blend/WPF/Silverlight team – and derives from the Smalltalk ApplicationModel pattern, as does the PresentationModel pattern described by Martin Fowler. It was first utilized by the Expression team (John was part of that team at the time) as they developed version 1 of Expression Blend. Without the WPF/Silverlight-specific aspects, the Model-View-ViewModel pattern is identical to PresentationModel.
In MVVM, the View and the ViewModel are typically instantiated by the container application. The View keeps a reference to the ViewModel. The ViewModel exposes commands and observable entities (“bindables”) that the View binds to (or to put it in programming terms, view.DataContext = viewModel;). User interactions with the View trigger commands on the ViewModel, and updates in the ViewModel are propagated to the View through data binding.
2.1. Simplistic Application Design
To demonstrate the use of the Model-View-X architecture, let’s consider a simple contacts application. The application has two windows (views): a table view, where you can see all entries in the contact book in a table, and a record view, where you can see individual records.
Fig. 1 UI of the contacts application
The Model-View separation for this particular problem feels natural, where the Model is the contact book and the Views are the two windows shown in Figure 1. So the trivial design (which is a two-tier Model-View-only design) would look as shown on Figure 2.
Fig. 2 Simplistic application design – the views are directly connected to the model
As shown, ContactBook keeps a list of views (which are added and removed with AttachView and DetachView). When a contact changes, ContactBook notifies all views by calling their Update methods, and all views update themselves by calling the model's GetContacts method. Upon instantiation, RecordView and TableView are given a reference to ContactBook, which they keep as a field (contactBook).
Notice how the two views are tightly coupled with the ContactBook class. Addition of business logic would only increase the level of coupling.
2.2. Simplistic Application Design – WPF/Silverlight Version
Before examining the design further, let’s convert the design to a WPF/Silverlight-friendly design. WPF/Silverlight provides the following native facilities that can be utilized directly:
- Databinding is the ability to bind UI elements to any data.
- Commands provide the ability to notify the underlying data of changes in the UI.
Using these facilities, the WPF/Silverlight-friendly design is changed as follows:
Fig. 3 WPF/Silverlight-friendly simplistic application design
In the modified design in Figure 3, the views derive from UserControl (there is no need for an abstract View class) and ContactBook no longer needs to maintain a list of views—ContactBook no longer needs to know about the views. Instead, the views point to ContactBook as their DataContext and use WPF data-binding to bind to the list of contacts.
You will also notice that List<Contact> has been replaced with ObservableCollection<Contact> to allow the views to bind to the ContactBook using WPF data-binding mechanisms.
Notice how WPF’s data-binding mechanism allows us to create a much more a loosely coupled design (at least until further addition of business logic).
2.3. Problems with the Simplistic Design
Things get more complicated if we introduce the following new functionality:
- Track the selected item, so that we update RecordView whenever the selection in TableView changes, and vice versa.
- Enable or disable parts of the UI of RecordView and TableView based on some rule (for example, highlight any entry that has an e-mail in the live.com domain).
Feature (a) can be implemented by adding a CurrentEntry property directly in ContactBook. This solution breaks down, however, if you have more than one instance of the UI connected to the same ContactBook. Feature (b) can be implemented in the views (RecordView and TableView). The problem if we do that, however, is that if we want to change the rule, then we would need to change both views.
Gradually it becomes apparent that we need a third layer in our application. We need a layer between the views and ContactBook that stores state shared by the views. We need a meta-view of sorts.
2.4. Enter Model-View-ViewModel (MVVM)
A ViewModel can serve as the third layer, providing an abstraction that acts as a meta-view (a model of a view), storing state and policy that are shared by a group of views. By introducing the concept of a ViewModel, our design changes to the following:
Fig. 4 Application design using a ViewModel
In this design, the views know of the ViewModel and bind to its data, to be able to reflect any changes in it. The ViewModel has no reference to the views—it holds only a reference to the model.
For the views, the ViewModel acts both as a façade to the model, but also as a way to share state between views (selectedContacts in the example). In addition, the ViewModel often exposes commands that the views can bind to and trigger.This use of commands is covered in the next section.
2.5. The use of commanding in MVVM Applications
WPF and Silverlight introduce a new input programming mechanism: commanding. Commands allow loose coupling between the origin and the handling of an action. Multiple sources can invoke the same command, and the same command can be handled differently depending on the target. All commands implement the ICommand interface.
For UI actions, WPF provides a specialized RoutedCommand class. A RoutedCommand is routed through the UI element tree, so the target of a RoutedCommand must be part of the UI element tree. In MVVM designs, however, command targets are often implemented in the ViewModels, which in turn are not typically part of the UI element tree. This requires the introduction of a different kind of command—the DelegateCommand—that implements ICommand and can have non-UI elements as its target.
Fig. 5 Application design using a ViewModel, exposing bindable commands
The DelegateCommand construct was originally introduced during the development of Microsoft Expression Blend version 1. A generic version of DelegateCommand was later released as part of the Composite Application Guidance for WPF on MSDN. Note that some MVVM sources refer to the same construct as RelayCommand.
A DelegateCommand is an ICommand that allows the views to bind to the ViewModel. Even though the diagram above does not show this explicitly, all ICommands exposed by the ViewModel are DelegateCommands. For example, the code for the AddContactCommand in the ViewModel may look as follows:
3. Benefits and Consequences of Using MVVM
The benefits of MVVM are the following:
- A ViewModel provides a single store for presentation policy and state, thus improving the reusability of the Model (by decoupling it from the Views) and the replaceability of the Views (by removing specific presentation policy from them).
- The Model-View-ViewModel design improves the overall testability of the application. One can easily create unit tests that target the Model and the ViewModel layers. The MVVM design also improves the “mockability” of the application, by allowing easy run-time simulation of the tiers, which is crucial to testing complex software products.
- The Model-View-ViewModel design is a very loosely coupled design. The View holds a reference to the ViewModel, and the ViewModel holds a reference to the Model. The rest is done by the data-binding and commanding infrastructure of WPF.
The consequences of MVVM are the following:
- The typical relationship between a ViewModel and the corresponding Views is one-to-many, but there are also situations where that is not necessarily true. In general, any business logic and input-handling business logic (selection tracking, and so on) is kept in the ViewModel.
- There are situations when one ViewModel is aware of another ViewModel within the same application. Such situations arise when there is a master-subordinate relationship between two ViewModels or when a ViewModel represents a single item (for example, the visual representation state of a single contact). When this happens, one ViewModel can represent a collection of ViewModels. Such a case in demonstrated in the 2nd part of documentation that comes with the WPF MVVM Toolkit.
4. Next Steps and References
Hopefully this post provides a simple introduction to the pattern. As a next step, download the WPF MVVM Toolkit, review the walk-through and the provided code and go write some apps.
It is important to note that there are a number of other (more full-featured) MVVM toolkits out there. Perhaps the most popular one is Laurent Bugnion’s MVVM Light, but there are many others on Codeplex. You should be using those for your WPF / Silverlight / Windows Phone and Windows 8 applications. Here are a few additional references that may help too:
- Presentation Model by Martin Fowler, July 2004.
- Introduction to Model/View/ViewModel pattern for building WPF apps by John Gossman, October 2005.
- Separated Presentation by Martin Fowler, June 2006.
- WPF Patterns by Bryan Likes, September 2006.
- WPF patterns: MVC, MVP or MVVM or…? by the Orbifold, December 2006.
- Model-see, Model-do, and the Poo is Optional by Mike Hillberg, May 2008.
- PRISM: Patterns for Building Composite Applications with WPF by Glenn Block, September 2008.
- The ViewModel Pattern by David Hill, January 2009.
- WPF Apps with the Model-View-ViewModel Design Pattern by Josh Smith, February 2009.