Skip to content

Model View ViewModel Pattern

jbe2277 edited this page Mar 31, 2024 · 8 revisions

Common abbreviations: M-V-VM or MVVM

1. Introduction

Separating user interface code from everything else is a key principle of well-designed software. But it's not always easy to follow, and it leads to more abstraction in an application that's hard to understand. Many design patterns try to address 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 Win Application Framework (WAF) provides support for the Model-View-ViewModel pattern. This pattern is also known as the PresentationModel pattern.

2. Definition

Represent the state and behavior of the presentation independently of the UI controls used in the interface.

A popular description of this design pattern comes from Martin Fowler. In his article, the pattern is called PresentationModel, but it is the same pattern. You can read his article online at his website. The following chapters describe our specific .NET implementation of this design pattern.

3. Structure

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
Figure 1: The structure of the Model-View-ViewModel Pattern

4. Participants

The types participating in this pattern are:

  • View contains the specific UI controls and defines the appearance of the user interface.
  • IView declares the interface of the View. The ViewModel can communicate with the View through this interface.
    • 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 that provides the necessary data.
  • Controller is responsible for the workflow of the application. It also mediates between the ViewModels. Thus, it promotes loose coupling by preventing the ViewModels from explicitly referencing each other.
    • Related patterns: Application Controller [PoEA], Mediator [GoF]

Remarks

  1. The introduction of the IView interface is a variation of the Model-View-ViewModel pattern. It allows the ViewModel to call properties and methods on the View.
  2. The Controller class is not part of the original M-V-VM pattern. This description shows how a controller works together with this pattern.

5. Collaborations

  • The View can call operations on the ViewModel directly. The ViewModel must communicate through the IView interface when it wants to update the view.
  • The View can interact with the Model, but it should be limited to simple data binding. It's recommended that more complex operations be handled by the ViewModel.
  • 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 allows the View to use data binding to synchronize data between the Model and the View.
    • Related pattern: Observer [GoF].
  • The Controller can call operations on the ViewModel directly, while the backward communication from the ViewModel to the Controller can be done through events.
    • Related pattern: Observer [GoF].

6. Liabilities

This particular implementation of the ViewModel pattern has the following liabilities:

  • The ViewModel may listen to events (e.g., PropertyChanged events) of the Model. In such a scenario, you must keep in mind the lifecycle of the ViewModel and the Model. If the Model lives longer than 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.

7. Usage

The Win Application Framework (WAF) provides some types to help you implement this pattern.

ViewModelCore class

Derive your ViewModel implementation from this class. The ViewModelCore class is responsible that the BindingContext (or DataContext) of the view gets the instance of your ViewModel.

IView interface

All views managed by a ViewModel must implement this interface. You can create your own interface for exposing properties and methods of the View.

DelegateCommand class

This class provides a simple implementation of the ICommand interface. The constructor takes a delegate that 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. The second delegate can be used to enable or disable the command. The command state refresh is triggered by the RaiseCanExecuteChanged method.

This command implementation is an ideal candidate for the ViewModel class. By using the DelegateCommand, the ViewModel is informed when it should handle a user interface action (e.g. Button was clicked). You must expose the commands in the ViewModel through properties and bind to them in the View.

8. Reference

Clone this wiki locally