After the term "view model (View-model)" appears, many developers have a lot of questions. It is clear that the view model needs to deal with the intersection of views, models, and external services, but the precise approach is often carried over by a single stroke. What it should contain, what it should not contain, the lack of a clear list, they tend to become a hodgepodge of everything. Instead of giving a clear answer, this article explores several of the many roles that the view model assumes.
As you read the different roles and patterns in this article, keep in mind the following three points:
These examples are from real projects.
Most view models assume multiple roles.
Strict adherence to a pattern is less important than a running program.
Role on model side
Providing data for a view is a vital role for the view model. However, even if you still use XAML data binding technology, there are a variety of ways to provide data.
Replacing a data context with a view model
Replacing the data context with a view model is the simplest model-side (Model-side) pattern and is probably the most common. Real data is exposed through one or more simple attributes of the view model. In a way, this is not a pattern. It simply associates the view model with the true data context attribute of the view and injects other functionality, such as wrapper navigation or the ICommand of the service invocation. This topic is also discussed later in this article.
To use a view model as an activity record
Unfortunately, the "model as active record" is a common error pattern. In this mode, there is no real model in the application. Instead, all fields are provided directly by the view model itself. For example, Customerviewmodel may contain FirstName, LastName, CustomerID fields. Because this is a view model, it is possible that external services are also hooked up. They can be exposed through icommand such as Loadcustomercommand and Savecustomercommand, which succeeds in turning the view model into an active record.
It is important to note that the activity logging pattern itself is quite effective in some scenarios. The problem is that the use of active records is somewhat exaggerated, and if they are used as other roles in the view model, they are almost universal objects (God object).
As shown in the picture, unit tests have no place to settle. You can create virtual unit tests by using an integration test with a simulation (mock) service, but this is often time-consuming and error-prone.
If there is no model, it is not MVVM.
To use the view model as an adapter or adorner
The view model can be either an adapter (adapter) or an adorner (decorator) to temporarily wrap a model, providing additional information or a new format. However, this is a very dangerous practice and should be avoided as long as it is possible.
We use the classic FullName as an example, which poses two risks.
The wrapper based on push
In a push-based wrapper (wrapper), we assume that only the view model can push data updates to the view.
public class Personviewmodel:
inotifypropertychanged
{
private readonly person M_model;
Public Personviewmodel (person model)
{
M_model = model;
}
public string FirstName
{
get{return m_model.firstname}
set
{
m_model.firstname = value;
OnPropertyChanged (New PropertyChangedEventArgs ("FirstName"));
OnPropertyChanged (New PropertyChangedEventArgs ("FullName"));
}
This means that the operation will fail if the model is not changed directly through the Personviewmodel wrapper. These changes do not propagate to the view, causing synchronization problems.