Xamarin Model-View-ViewModel Pattern
MVVM stands for Model-View-ViewModel. MVVM stands as a separation of code into the domain-relevant data (the model) and the representation of the data (View) and, finally, the logic (called the business logic) of our program (ViewModel). The responsibility of ViewModel is visibility.
Xamarin.Forms developer involves creating a user interface in XAML, and then we would add code behind the operations on the User Interface. As the apps modified and grow in size and scope, the issue of maintenance arises. These issues include the tight coupling between the UI control and the business logic, which increases the cost of the UI modification and will face the difficulty in unit testing of the code.
The Model-View-ViewModel (MVVM) pattern helps to separate the business and presentation logic of an application from its user interface. Maintaining a clean separation between the application logic and the UI helps to address the different issues and can make an application easier to test, maintain, and evolve. It can also improve the code re-use opportunity and allows the developers and UI designers to collaborate easily when we develop the respective parts of the app.
MVVM contains the three core components: the Model, the View, and the view model. Each serves different functionality.
Here we will show the different relationship between the three components:
Besides, to understand the responsibility of each component, it is also important to know how they interact with each other.At a high level, view "knows about" the view model and the view model knows about the model, but the model is unaware of the view model, and view model is unaware of the View. Therefore, the view model isolates the View from the model and allows the model to evolve independently of the View.
Benefits of MVVM Pattern
Benefits of using the MVVM pattern are:
The View is responsible for defining the layout of the structure and the appearance of the screen. Each View is defined in XAML; it contains the limited code which doesn't include the business logic. In some cases, code-behind might provide the UI logic, which implements the visual behavior, which is difficult to express in XAML, such as animation.
In Xamarin.Forms application, View is a Page type or ContentView-derived class. Views can also be presented by a data template, which specifies the UI element used to visualize the object when it is displayed. Data-Template, as a view, does not have any code-behind, and it is designed to bind to the specific view model type. There are several options present for executing the code on the view model to interact with the View, such as a button-click or item selection. If a control supports commands, control's command can be data-bound to an Icommand property on the view model. When the control's command invoked, the code in the view model will be executed. In addition to commands, behavior can be attached to an object in the View and can listen for a command to be invoked or event to be raised. In that response, behavior can then invoke an Icommand on the view model or a method on the view model.
The view model implements the properties and commands to which the View can bind the data, and informs the View of any state to change through change notification events. The commands and properties of the view model define the functionality of the UI, but View determines how the functionality is displayed.
View Model is also responsible for coordinating the View's interaction with any model classes which are required. View model might choose to expose the model classes directly to the View so that controls in the View can bind the data directly to them. In this case, model classes need to be designed to support data binding and change notification events. Each view model provides the data in a form that the view model can consume easily. View model sometime performs the conversion of the data. Placing the conversion in the view model is a good idea because it provides the properties that the View can bind to. For example, the view model might combine the values of two properties to make it easier for display by the View.
For the view model to participate in two-way data binding with the View, its properties must raise the PropertyChanged event.
View models meet this requirement by implementing the INotifyPropertyChanged interface and extending the PropertyChanged event when a property is changed.
For collections, the view-friendly ObjervableCollection<T> is provided. This collection implements the collection changed notification, relieving the developer from having to implement the INotifyCollectionChanged interface on collections.
Model classes are non-visual classes that encapsulate the app's data. Therefore, the model can be thought of as representing the app's domain model, which usually includes the data model along with business and validation logic.
Examples of the model object include the data transfer object (DTOs), Plain Old CLR Objects (POCOs), and generated the entity and proxy objects. Model classes are typically used in conjunction with services or repositories, which encapsulate the data access and caching.
Connecting View Models to Views
View models can be linked to views using the data-binding capabilities of Xamarin.Forms.
Several approaches can be used to construct views and view models and add them at runtime.
These approaches fall into two categories, known as the view first composition, and the view model first composition. There is an issue of preference and complexity chosen between the View first composition and view model first composition. However, all approaches share the same aim, which is for the View to have a view model assigned to its BindingContext property.
View First Composition
The benefit of this approach is that it makes it easy to construct the loosely coupled, unit-testable apps because the view models have no dependence on the views themselves. It is easy to understand the structure of the app by following its visual structure rather than having a track the execution of the code to know how the classes are created and associated. Also, Viewfirst construction aligns with the Xamarin. Forms navigation system which is responsible for constructing the pages when navigation occurs, which makes the view model first composition complex and misaligned with the platform.
View Model First Composition
View model first composition feels more natural to some developers. Since the view creation can be abstracted away, and allowing them to focus on the logical non-UI structure of the app. Also, it can enable view models to be created by other view models. However, this approach is often complex, and it can difficult to understand how the various parts of the app are created and associated.
Here are the approaches for connecting the view models to views.
Creating a view model declaratively
The most straightforward approach for the View is to initialize its corresponding view model in XAML declaratively. When the View is constructed, the corresponding view model object will also be constructed.
We will discuss this approach through the following code:
When the ContentPage is created, an instance of the LoginViewModel is automatically constructed and set as the view's BindingContext.
The Advantage of this is that it is simple, but the Disadvantages of this that it requires a default constructor in the view model.
Creating a view model programmatically
A view can have code in the code-behind file that results in the view-model being assigned to its BindingContext property. This is often accomplished in the View's constructor, which is shown in the following code:
The programmatic construction and assignment of the view model within the View's code-behind have the advantage that it's simple. The disadvantage of this approach is that the View needs to provide the view model with any required dependencies.
Creating a View Defined as a Data Template
A view can be defined as a data template and associated with a view model type. Data templates can be defined as resources, or they can be defined inline within the control, which will display the view model. The content of the control is the view model instance, and the data template is used to represent it visually. This technique is an example of a situation in which the view model initializes first, followed by the creation of the View.
Automatically Creating a View Model with a View Model Locator
A view model locator is a custom class which manages the initialization of the view models and their association to views. In the EShopOnContainers mobile app, the ViewModelLocator class has an attached property, AutoWireViewModel, which is used to connect views to the view model. In the View's XAML, this attached property is set to true to indicate that the view model should be automatically connected to the views which are shown in the following code:
The AutoWireViewModel property is a bindable property that is initialized to false, and when the value changes, the OnAutoWireViewModelChanged event handler is called. This method resolves the view model for the View.
The OnAutoWireViewModelChanged method attempts to resolve the view model using a convention-based approach. This convention assumes that:
Finally, the OnAutoWireViewModelChanged method sets the BindingContext of the view type to the resolved view model type for determining the more information about the view model type. This approach has the advantage that an app has a single class that is responsible for the initialization of view models and their connection to views.
The Model-View-ViewModel(MVVM) pattern helps to separate the business and presentation logic of an application from its user interface (UI). Maintaining a clean separation between the application logic, and the UI which helps to address the numerous development issues and can make the application easier to test, maintain, and evolve. It can also improve the code re-use opportunity and allows the developer and UI designer to easily collaborate when we are developing their respective parts of the app.
With the use of the MVVM pattern, the UI of the app, underlying presentation and business logic are separated into three classes. Classes are the View, which encapsulates the presentation logic and state, and the model, which encapsulates business logic and the data.