The Model-View-ViewModel Design Pattern
The Model-View-ViewModel (MVVM) pattern helps you to cleanly separate the business and presentation logic of your application from its user interface (UI). Maintaining a clean separation between application logic and UI helps to address numerous development and design issues and can make your application much easier to test, maintain, and evolve. It can also greatly improve code re-use opportunities and allows developers and UI designers to more easily collaborate when developing their respective parts of the application.
Using the MVVM pattern, the UI of the application and the underlying presentation and business logic is separated into three separate classes:
1- The view, which encapsulates the UI and UI logic
2- The view model, which encapsulates presentation logic and state
3- The model, which encapsulates the application’s business logic and data
The MVVM pattern is a close variant of the Presentation Model pattern, optimized to leverage some of the core capabilities of WPF, such as data binding, data templates, commands, and behaviors. In the MVVM pattern, the view interacts with the view model through data binding, commands, and change notification events. The view model queries, observes, and coordinates updates to the model, converting, validating, and aggregating data as necessary for display in the view.
The following illustration shows the three MVVM classes and their interaction.
The View Class
The view’s responsibility is to define the structure and appearance of what the user sees on the screen. Ideally, the code-behind of a view contains only a constructor that calls the InitializeComponent method. The view usually has the following key characteristics:
- The view is a visual element, such as a window, page, user control, or data template.
- The view defines the controls contained in the view and their visual layout and styling.
- The view references the view model through its DataContext property.
- The controls are data bound to properties and commands exposed by the view model.
- The view may customize the data binding behavior between the view and the view model.
- The view defines and handles UI visual behavior, such as animations.
- The view’s code-behind may implement visual behavior that is difficult to express in XAML.
The View Model Class
The view model in the MVVM pattern encapsulates the presentation logic for the view. It has no direct reference to the view or any knowledge about the view’s specific implementation or type. The view model implements properties and commands to which the view can data bind and notifies the view of any state changes through change notification events. The properties and commands that the view model provides define the functionality to be offered by the UI, but the view determines how that functionality is to be rendered.
The view model is responsible for coordinating the view’s interaction with any model classes that are required. Typically, there is a one-to many-relationship between the view model and the model classes. The view model may choose to expose model classes directly to the view so that controls in the view can data bind directly to them. The view model may convert or manipulate model data so that it can be easily consumed by the view.
The view model may also define logical states the view can use to provide visual changes in the UI. The view may define layout or styling changes that reflect the state of the view model. For example, the view model may define a state that indicates that data is being submitted asynchronously to a web service. The view can display an animation during this state to provide visual feedback to the user.
Typically, the view model will define commands or actions that can be represented in the UI and that the user can invoke. A common example is when the view model provides a Submit command that allows the user submit data to a web service or to a data repository. The view may choose to represent that command with a button so that the user can click the button to submit the data. Typically, when the command becomes unavailable, its associated UI representation becomes disabled. The view model usually has the following key characteristics:
- The view model is a non-visual class. It encapsulates the presentation logic.
- The view model is testable independently of the view and the model.
- The view model typically does not directly reference the view.
- The view model implements properties and commands to which the view can data bind.
- The view model notifies the view of any state changes via change notification events:
INotifyPropertyChanged and INotifyCollectionChanged
- The view model coordinates the view’s interaction with the model.
- The view model may define logical states that the view can represent visually to the user.
The Model Class
The model in the MVVM pattern encapsulates business logic and data. Business logic is defined as any application logic that is concerned with the retrieval and management of application data and for making sure that any business rules that ensure data consistency and validity are imposed. To maximize re-use opportunities, models should not contain any use case–specific or user task–specific behavior or application logic.
Typically, the model represents the client-side domain model for the application. The model may also include the code to support data access and caching, though typically a separate data repository or service is employed for this. Often, the model and data access layer are generated as part of a data access or service strategy, such as the ADO.NET Entity Framework, WCF Data Services, or WCF RIA Services.
The model implements the facilities that make it easy to bind to the view. This usually means it supports property and collection changed notification through the INotifyPropertyChanged and INotifyCollectionChanged interfaces. Models classes that represent collections of objects typically derive from the ObservableCollection<T> class, which provides an implementation of the INotifyCollectionChanged interface.
The model may also support data validation and error reporting through the IDataErrorInfo (or INotifyDataErrorInfo) interfaces. These interfaces allow WPF data binding to be notified when values change so that the UI can be updated. The model usually has the following key characteristics:
- Model classes are non-visual classes that encapsulate the application’s data.
- The model classes do not directly reference the view or view model classes.
- The model classes have no dependency on how they are implemented.
- The model classes typically provide property and collection change events through:
- The Model classes typically derive from the ObservableCollection<T> class.
- The model classes typically provide data validation and error reporting through:
- The model classes are typically used with a service that encapsulates data access.