In this article by Steven F. Daniel, author of the book Mastering Xamarin UI Development, you will learn how to build stunning, maintainable, cross-platform mobile application user interfaces with the power of Xamarin.
In this article, we will cover the following topics:
(For more resources related to this topic, see here.)
In this section we will be taking a look at the MVVM pattern architecture and the communication between the components that make up the architecture.
The MVVM design pattern is designed to control the separation between the user interfaces (Views), the ViewModels that contain the actual binding to the Model, and the models that contain the actual structure of the entities representing information stored on a database or from a web service.
The following screenshot shows the communication between each of the components contained within the MVVM design pattern architecture:
The MVVM design pattern is divided into three main areas, as you can see from the preceding screenshot and these are explained in the following table:
MVVM type |
Description |
Model |
The Model is basically a representation of business related entities used by an application, and is responsible for fetching data from either a database, or web service, and then de-serialized to the entities contained within the Model. |
View |
The View component of the MVVM model basically represents the actual screens that make up the application, along with any custom control components, and control elements, such as buttons, labels, and text fields. The Views contained within the MVVM pattern are platform-specific and are dependent on the platform APIs that are used to render the information that is contained within the application's user interface. |
ViewModel |
The ViewModel essentially controls, and manipulates the Views by acting as their main data context. The ViewModel contains a series of properties that are bound to the information contained within each Model, and those properties are then bound to each of the Views to represent this information within the user interface. ViewModels can also contain command objects that provide action-based events that can trigger the execution of event methods that occur within the View. For example, when the user taps on a toolbar item, or a button. ViewModels generally implement the INotifyPropertyChanged interface. Such a class fires a PropertyChanged event whenever one of their properties change. The data binding mechanism in Xamarin.Forms attaches a handler to this PropertyChanged event so it can be notified when a property changes and keep the target updated with the new value. |
Now that you have a good understanding of the components that are contained within MVVM design pattern architecture, we can begin to create our entity models and update our user interface files.
In Xamarin.Forms, the term View is used to describe form controls, such as buttons and labels, and uses the term Page to describe the user interface or screen. Whereas, in MVVM, Views are used to describe the user interface, or screen.
In this section, we will begin by setting up the basic structure for our TrackMyWalks solution to include the folder that will be used to represent our ViewModels. Let's take a look at how we can achieve this, by following the steps:
In this section, we will begin by creating a base MVVM ViewModel that will be used by each of our ViewModels when we create these, and then the Views (pages) will implement those ViewModels and use them as their BindingContext.
Let's take a look at how we can achieve this, by following the steps:
Create an empty class within the ViewModels folder, shown in the following screenshot:
//
// WalkBaseViewModel.cs
// TrackMyWalks Base ViewModel
//
// Created by Steven F. Daniel on 22/08/2016.
// Copyright © 2016 GENIESOFT STUDIOS. All rights reserved.
//
using System.ComponentModel;
using System.Runtime.CompilerServices;
namespace TrackMyWalks.ViewModels
{
public abstract class WalkBaseViewModel : INotifyPropertyChanged
{
protected WalkBaseViewModel()
{
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var handler = PropertyChanged;
if (handler != null)
{
handler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
In the preceding code snippet, we begin by creating a new abstract class for our WalkBaseViewModel that implements from the INotifyPropertyChanged interface class, that allows the View or page to be notified whenever properties contained within the ViewModel have changed. Next, we declare a variable PropertyChanged that inherits from the PropertyChangedEventHandler that will be used to indicate whenever properties on the object have changed. Finally, within the OnPropertyChanged method, this will be called when it has determined that a change has occurred on a property within the ViewModel from a child class.
The INotifyPropertyChanged interface is used to notify clients, typically binding clients, when the value of a property has changed.
In the previous section, we built our base class ViewModel for our TrackMyWalks application, and this will act as the main class that will allow our View or pages to be notified whenever changes to properties within the ViewModel have been changed.
In this section, we will need to begin building the ViewModel for our WalksPage,. This model will be used to store the WalkEntries, which will later be used and displayed within the ListView on the WalksPage content page.
Let's take a look at how we can achieve this, by following the steps:
First, create a new class file within the ViewModels folder called WalksPageViewModel, as you did in the previous section, entitled Creating the WalkBaseViewModel located within this article.
//
// WalksPageViewModel.cs
// TrackMyWalks ViewModels
//
// Created by Steven F. Daniel on 22/08/2016.
// Copyright © 2016 GENIESOFT STUDIOS. All rights reserved.
//
using System.Collections.ObjectModel;
using TrackMyWalks.Models;
namespace TrackMyWalks.ViewModels
{
public class WalksPageViewModel : WalkBaseViewModel
{
ObservableCollection<WalkEntries> _walkEntries;
public ObservableCollection<WalkEntries> walkEntries
{
get { return _walkEntries; }
set
{
_walkEntries = value;
OnPropertyChanged();
}
}
In the above code snippet, we begin by ensuring that our ViewModel inherits from the WalkBaseViewModel class. Next, we create an ObservableCollection variable _walkEntries which is very useful when you want to know when the collection has changed, and an event is triggered that will tell the user what entries have been added or removed from the WalkEntries model.
In our next step, we create the ObservableCollection constructor WalkEntries, that is defined within the System.Collections.ObjectModel class, and accepts a List parameter containing our WalkEntries model. The WalkEntries property will be used to bind to the ItemSource property of the ListView within the WalksMainPage. Finally, we define the getter (get) and setter (set) methods that will return and set the content of our _walkEntries when it has been determined when a property has been modified or not.
public WalksPageViewModel()
{
walkEntries = new ObservableCollection<WalkEntries>() {
new WalkEntries {
Title = "10 Mile Brook Trail, Margaret River",
Notes = "The 10 Mile Brook Trail starts in the Rotary Park near Old Kate, a preserved steam " +
"engine at the northern edge of Margaret River. ",
Latitude = -33.9727604,
Longitude = 115.0861599,
Kilometers = 7.5,
Distance = 0,
Difficulty = "Medium",
ImageUrl = "http://trailswa.com.au/media/cache/media/images/trails/_mid/" +
"FullSizeRender1_600_480_c1.jpg"
},
new WalkEntries {
Title = "Ancient Empire Walk, Valley of the Giants",
Notes = "The Ancient Empire is a 450 metre walk trail that takes you around and through some of " +
"the giant tingle trees including the most popular of the gnarled veterans, known as " +
"Grandma Tingle.",
Latitude = -34.9749188,
Longitude = 117.3560796,
Kilometers = 450,
Distance = 0,
Difficulty = "Hard",
ImageUrl = "http://trailswa.com.au/media/cache/media/images/trails/_mid/" +
"Ancient_Empire_534_480_c1.jpg"
},
};
}
}
}
In the preceding code snippet, we began by creating a new ObservableCollection for our walkEntries method and then added each of the walk list items that we would like to store within our model. As each item is added, the ObservableCollection, constructor is called, and the setter (set) method is invoked to add the item, and then the INotifyPropertyChanged event will be triggered to notify that a change has occurred.
In this article, you learned about the MVVM pattern architecture; we also implemented the MVVM ViewModels within the app. Additionally, we created and implemented the WalkBaseViewModel for the TrackMyWalks application.
Further resources on this subject: