Understanding the basics of MVVM design pattern
This article is dedicated for beginners who would like to know more about Model-View-ViewModel (MVVM) design pattern and why MVVM has to be used.
Why use MVVM?
In traditional UI development - developer used to create a View using window or user control or page and then write all logical code (Event handling, initialization and data model, etc.) in the code behind and hence they were basically making code as a part of view definition class itself. This approach increased the size of the View class and created a very strong dependency between my UI and data binding logic and business operations. In this situation, no two developers can work simultaneously on the same view and also one developer's changes might break the other code. So everything is in one place is always a bad idea for maintainability, extendibility and testability prospective. So if you look at the big picture, you can feel that all these problems exist because there is a very tight coupling between the following items.
- View (UI)
- Model (Data displayed in UI)
- Glue code (Event handling, binding, business logic)
In MVVM the Glue code is View Model. So it basically focuses on separation of concerns to make the implementation of an application structure a lot more simpler to create as well as maintain.
If property values in the ViewModel
change, those new values automatically propagate to the view via data binding and via notification. When the user performs some action in the view for example clicking on save button, a command on the ViewModel
executes to perform the requested action. In this process, it’s the ViewModel
which modifies model
data, View
never modifies it. The view
classes have no idea that the model
classes exist, while the ViewModel
and model are unaware of the view
. In fact, the model
doesn’t have any idea about ViewModel
and view
exists.
What is MVVM?
A simple representation of MVVM design pattern for a news reader application
A simple MVVM implementation example in C#
Here is a simple code implementation example in C#:
Model:
public class Book
{
public string Title { get; set; }
public string Author { get; set; }
public string Category { get; set; }
public string Language { get; set; }
}
View Model:
public class MainPageViewModel : BindableBase
{
private List<Book> books;
public List<Book> Books
{
get
{
return books;
}
set
{
SetProperty(ref books, value);
}
public MainPageViewModel()
{
Books = new List<Book>();
Books.Add(new Book
{
Title = “Harry Potter”,
Author = “J. K. Rowling”,
Category = “Young-adult fiction”,
Language = “English”
});
Books.Add(new Book
{
Title = “Written Lives”,
Author = “Javier Marias”,
Category = “Biography”,
Language = “Spanish”
});
}
}
BindableBase Class:
public class BindableBase : INotifyPropertyChanged
{
///
/// Multicast event for property change notifications.
///
public event PropertyChangedEventHandler PropertyChanged;
///
/// Checks if a property already matches a desired value. Sets the property and
/// notifies listeners only when necessary.
///
///Type of the property.
///Reference to a property with both getter and setter.
///Desired value for the property.
///Name of the property used to notify listeners. This
/// value is optional and can be provided automatically when invoked from compilers that
/// support CallerMemberName.
///True if the value was changed, false if the existing value matched the
/// desired value.
protected bool SetProperty(ref T storage, T value, [CallerMemberName] String propertyName = null)
{
if (object.Equals(storage, value)) return false;
storage = value;
this.OnPropertyChanged(propertyName);
return true;
}
///
/// Notifies listeners that a property value has changed.
///
///Name of the property used to notify listeners. This
/// value is optional and can be provided automatically when invoked from compilers
/// that support .
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
var eventHandler = this.PropertyChanged;
if (eventHandler != null)
{
eventHandler(this, new PropertyChangedEventArgs(propertyName));
}
}
}
View:
<TextBlock x:Name="bookTitle” HorizontalAlignment="Left" TextWrapping="Wrap"
Text="{Binding Title}" VerticalAlignment="Top"/>
<TextBlock x:Name="bookAuthor” HorizontalAlignment="Left" TextWrapping="Wrap"
Text="{Binding Author}" VerticalAlignment="Top" Margin="0,142,0,0"/>
<TextBlock x:Name="bookCategory” HorizontalAlignment="Left" TextWrapping="Wrap"
Text="{Binding Category}" VerticalAlignment="Top" Margin="0,242,0,0"/>
<TextBlock x:Name="bookLanguage” HorizontalAlignment="Left" TextWrapping="Wrap"
Text="{Binding Language}" VerticalAlignment="Top" Margin="0,342,0,0"/>
If property values in the ViewModel
change, those new values automatically propagate to the view via data binding and via notification. When the user performs some action in the view for example clicking on save button, a command on the ViewModel
executes to perform the requested action. In this process, it’s the ViewModel
which modifies Model
data, View
never modifies it. The View
classes have no idea that the Model
classes exist, while the ViewModel
and model are unaware of the View
. In fact, the Model
doesn’t have any idea about ViewModel
and View
exists.
References:
https://www.codeproject.com/Articles/186705/A-Totally-Simple-Introduction-to-the-MVVM-Concept