PROWAREtech
Xamarin: Tutorial - Page 07
MVVM: Model-View-ViewModel
An MVVM application is divided into three parts.
- The Model part which provides the data.
- The View part which is the user interface.
- The ViewModel part which connects the previous two parts. It "translates" the data making it more agreeable between the View and Model parts.
MVVM is designed to take advantage of XAML based data bindings which has already been covered by this tutorial.
For a ViewModel (or Model) to be a data-binding source it must implement a notification protocol to let the View know when a
property has changed. What this means is that the ViewModel (and Model) classes must inherit from the
INotifyPropertyChanged
interface and then, from within the property's set
, call the
PropertyChangedEventHandler::Invoke()
method. All MVVM applications have this in common and it must be adhered
to in order to successfully write this type of application.
Example Code
Notice that both Label
and Entry
are bound to the MainText
property. This means that as
the text of Entry
changes then the property MainText
changes which causes an event to execute letting
the Label
know that the property has changed. Label
then updates its text.
<?xml version="1.0" encoding="utf-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:HelloXamarinForms"
x:Class="HelloXamarinForms.MainPageXaml"
BackgroundColor="White">
<ContentPage.Padding>
<OnPlatform x:TypeArguments="Thickness" iOS="0, 20, 0, 0" />
</ContentPage.Padding>
<StackLayout VerticalOptions="Center" HorizontalOptions="FillAndExpand">
<Label Text="{Binding MainText}" TextColor="Black" HorizontalTextAlignment="Center" />
<Entry Text="{Binding MainText}" />
</StackLayout>
</ContentPage>
The code-behind file.
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class MainPageXaml : ContentPage
{
public MainPageXaml()
{
InitializeComponent();
}
}
}
Add a new C# class file to the project for the ViewModel.
// ViewModel.cs
using System.ComponentModel;
namespace HelloXamarinForms
{
class ViewModel : INotifyPropertyChanged
{
private string mainText;
public string MainText
{
get
{
return mainText;
}
set
{
if (value == mainText)
return;
mainText = value;
OnPropertyChanged(nameof(MainText));
}
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
}
Modify the App.xaml.cs file to create the ViewModel and set the its MainText
property to an initial value.
// App.xaml.cs
using Xamarin.Forms;
namespace HelloXamarinForms
{
public partial class App : Application
{
public App()
{
ViewModel viewModel = new ViewModel();
viewModel.MainText = "Hello Mvvm!";
MainPage = new MainPageXaml()
{
BindingContext = viewModel
};
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
Because this is a simple example of MVVM, a model is not needed as it does not deal with any data. However, the following example
is a good one because it inherits INotifyPropertyChanged
and calls the PropertyChangedEventHandler
as it
should. Everytime the Name
is changed, the property-changed event executes.
For a working model, see the Phonebook example.
// ExampleModel.cs
using System.ComponentModel;
namespace HelloXamarinForms
{
class Model : INotifyPropertyChanged
{
private string name;
public string Name
{
get
{
return name;
}
set
{
if (value == name)
return;
name = value;
OnPropertyChanged(nameof(Name));
}
}
public event PropertyChangedEventHandler PropertyChanged;
void OnPropertyChanged(string propName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propName));
}
}
}
MVVM will continue to be used throughout this tutorial as well as on the ListView
article and the TableView
article.