-
Notifications
You must be signed in to change notification settings - Fork 130
DataModel View ViewModel Pattern
Common abbreviations: DM-V-VM
Full name in a bottom-up order: Model-DataModel-ViewModel-View Pattern
The DataModel-View-ViewModel design pattern is an extension of the Model-View-ViewModel design pattern. Please read the description of the Model-View-ViewModel design pattern first.
This design pattern introduces a new class, called DataModel. This class does not replace the Model. Instead, it is responsible for wrapping the Model in a UI-friendly way. Here are some examples of what the DataModel might do:
- Provide Commands that map to some functionality of the Model.
- Manage application state related to the Model (e.g., selection state).
- Encapsulate properties of the Model and provide change notifications so that any View that uses this DataModel is updated.
ViewModel: Represent the state and behavior of the presentation independently of the UI controls used in the interface.
DataModel: Represent the state and behavior of Models in a UI-friendly way, but independent of the UI controls used in the interface.
The following UML class diagram shows the collaborating classes of this design pattern in a logical layered architecture.
Figure 1: The structure of the DataModel-View-ViewModel Pattern
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.
- DataModel represents the state and behavior of the model in a UI-friendly way.
- 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]
Remark
- The Controller is responsible for creating the DataModel objects. This is represented by the composite aggregation in the UML diagram.
- A DataModel object can be shared between different ViewModels.
- The association showing that the View can access the Model directly is not drawn in the diagram. However, the View should restrict this access to simple data binding.
The following list includes only collaborations that involve the DataModel.
- The View can call operations on the DataModel directly. The DataModel must communicate through events if it wants to notify the View.
- The View can interact with the Model, but this should be limited to simple data binding. It's recommended that more complex operations be handled by the DataModel.
- Upward communication from the Model to the View or to the DataModel can be done through events. In particular, the property changed events can be raised on the Model to trigger the data binding implementation.
- Related pattern: Observer [GoF].
- The Controller can call operations on the DataModel directly, while the backward communication from the DataModel to the Controller can be done through events.
- Related pattern: Observer [GoF].
This particular implementation of the DataModel pattern has the following liabilities:
- The DataModel can listen to events (e.g.,
PropertyChanged
events) of the Model. In such a scenario, you must consider the lifecycle of the DataModel and the Model. If the Model lives longer than the DataModel, it is essential to unwire the event or to use weak events so that the garbage collector is able to remove the DataModel instance.
The Win Application Framework (WAF) supports the ViewModel and the DataModel patterns. The question may arise when to use which pattern:
- The ViewModel is often used with a Window, Page, or ContentView on the View side.
- The DataModel is often used with a DataTemplate on the View side.
- The ViewModel has a direct relationship with the View.
- The DataModel has a direct relationship to the Model.
The Win Application Framework (WAF) provides some types to help you implement this pattern.
Derive your DataModel implementation from this class. The Model class provides an implementation of the INotifyPropertyChanged
interface.
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 DataModel. By using the DelegateCommand, the DataModel is informed when it should handle a user interface action (e.g. Button was clicked). You must expose the commands in the DataModel through properties and bind to them in the View.
If you need to synchronize a Model collection with an associated DataModel collection, you may find the SynchronizingList useful. It listens to the CollectionChanged
event of the Model collection and synchronizes the DataModel collection.
- PoEA – Patterns of Enterprise Architecture by Martin Fowler
- GoF – Design Patterns by Erich Gamma, Richard Helm, Ralph Johnson and John M. Vlissides
- Weak Event