Learn MVVM Pattern

Overview

There is a vast array of tutorials over the internet about the MVVM pattern and sadly most of them do not break the pattern down to the bare essentials. I will not say that their approach to teaching the pattern is wrong or that mine is the end all and be all method. Everyone learns differently and sometimes the basic approach is the best. That being said, I will do my best to explain the MVVM pattern with the basic implementation in mind.

This tutorial is broken down into two sections. Section 1 is theory with explanations. Section 2 is a simple project with a breakdown on the important pieces of code to understand. Let's get started with Section 1.

Section 1

The MVVM pattern is an extension to the MVC pattern that is mainly used in Web development. Instead of Model View Controller, it features a Model View and ViewModel. So, if you are a beginner to the MVVM pattern, you are probably wondering why this pattern is so important. You would be right to wonder this and the reasoning is quite simple. Code separation. Code separation allows you to keep your UI and your back end code separate. This is especially useful in various situations.

A primary example is, you are working on backend code while another developer is working on the UI. If you don't use the MVVM pattern, any changes the UI developer makes could break your code. The MVVM pattern helps eliminate this problem.

Additionally, whenever you use the MVVM pattern, it is important to note that you are now doing a declarative programming style.

What each portion of the MVVM model means and does

The Model is a class that exposes the data you want to use. In addition, this class also implements the INotifyPropertyChanged Interface.

The View is either your page or usercontrol (whichever you decide to use). This class should not have any backend code to it, however, there is one exception to this rule, that is Setting the DataContext to the ViewModel.

The ViewModel is a class that does all of the heavy lifting. This is where you would call a database, create an observablecollection and any other backend code you would need to implement.

Why DataBinding is important with MVVM

Databinding enables the user to bind objects so that whenever the other object changes, the main object reflects its changes. The main motive is to ensure that the UI is always synchronized with the internal object structure automatically.

How to use DataBinding

In XAML, databinding is very simple to do. Consider the following snippet:

  1. <TextBox x:Name="textBox" Height="34" TextWrapping="Wrap" Text="{Binding Genre}" IsReadOnly="True"/>  
What XAML snippet is telling us is that the TextBox text is set to the Bound path of Genre.

Now, what if you want to write the code using C# instead of using XAML? Well, consider the following snippet:
  1. BindingSource binding = new BindingSource();  
  2. binding.Add(new Models.ModelClass("Action");  
  3. textbox.text = binding;  
Now that the preliminaries are done, let's go to Section 2 and have some fun with code!

Section 2

First, let's talk about the model class.

In this example, we want to expose ReleaseDate, Name and Genre. We also want to implement the INotifyPropertyChanged Interface and call the event in the setter of each public property.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.ComponentModel;  
  4. using System.Linq;  
  5. using System.Runtime.CompilerServices;  
  6. using System.Text;  
  7. using System.Threading.Tasks;  
  8.   
  9. namespace PracticeProject.Models  
  10. {  
  11.     public class ModelClass : INotifyPropertyChanged  
  12.     {  
  13.         private string name;  
  14.         public string Name  
  15.         {  
  16.             get { return name; }  
  17.             set  
  18.             {  
  19.                 name = value;  
  20.                 NotifyPropertyChanged();  
  21.             }  
  22.         }  
  23.         private string releaseDate;  
  24.         public string ReleaseDate  
  25.         {  
  26.             get { return releaseDate; }  
  27.             set  
  28.             {  
  29.                 releaseDate = value;  
  30.                 NotifyPropertyChanged();  
  31.             }  
  32.         }  
  33.         private string genre;  
  34.         public string Genre  
  35.         {  
  36.             get { return genre; }  
  37.             set  
  38.             {  
  39.                 genre = value;  
  40.                 NotifyPropertyChanged();  
  41.             }  
  42.         }  
  43.   
  44.         public event PropertyChangedEventHandler PropertyChanged;  
  45.         private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")  
  46.         {  
  47.             if (PropertyChanged != null)  
  48.             {  
  49.                 PropertyChanged(thisnew PropertyChangedEventArgs(propertyName));  
  50.             }  
  51.         }  
  52.     }  
  53. }  
Next up, The ViewModel Class. In the example, we will take advantage of using an ObservableCollection and set the parameters to be the Model Class. We will use LINQ and lambda expressions to enumerate over the ObservableCollection. The XML file is embedded into the application, so we will use reflection and the StreamReader class to call this data and put it into the ObservableCollection.
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Collections.ObjectModel;  
  4. using System.ComponentModel;  
  5. using System.Linq;  
  6. using System.Runtime.CompilerServices;  
  7. using System.Text;  
  8. using System.Threading.Tasks;  
  9. using System.Windows.Input;  
  10. using System.Xml.Linq;  
  11. using System.IO;  
  12. using System.Reflection;  
  13. using System.Windows;  
  14. namespace PracticeProject.ViewModels  
  15. {  
  16.     public class ViewModelClass  
  17.     {  
  18.         public ObservableCollection<Models.ModelClass> Movies { getset; }  
  19.         StreamReader _textStreamReader;  
  20.         public ViewModelClass()  
  21.         {  
  22.            LoadEmbeddedResource("PracticeProject.DataSources.Movies.xml");  
  23.             XDocument xdoc = XDocument.Load(_textStreamReader);  
  24.             var movies = xdoc.Descendants("Movies")  
  25.                 .Select(x =>  
  26.                 new Models.ModelClass  
  27.                 {  
  28.                     Name = (string)x.Element("Name"),  
  29.                     Genre = (string)x.Element("Genre").Value,  
  30.                     ReleaseDate = (string)x.Element("ReleaseDate").Value  
  31.                 }  
  32.                 ).ToList();  
  33.             Movies = new ObservableCollection<Models.ModelClass>(movies);  
  34.         }  
  35.         private void LoadEmbeddedResource(string resource)  
  36.         {  
  37.             try  
  38.             {  
  39.                 Assembly _assembly;  
  40.                 _assembly = Assembly.GetExecutingAssembly();  
  41.                 _textStreamReader = new StreamReader(_assembly.GetManifestResourceStream(resource));  
  42.             }  
  43.             catch (Exception ex)  
  44.             {  
  45.                 MessageBox.Show("Error Loading Embedded Resource: " + ex, "Error!", MessageBoxButton.OK, MessageBoxImage.Error);  
  46.             }  
  47.         }  
  48.     }  
  49. }  
Third on our plate is the View's CodeBehind. This example will illustrate that you shouldn't have any backend code for it, although it is acceptable for one line as in the following:
  1. using System;  
  2. using System.Collections.Generic;  
  3. using System.Linq;  
  4. using System.Text;  
  5. using System.Threading.Tasks;  
  6. using System.Windows;  
  7. using System.Windows.Controls;  
  8. using System.Windows.Data;  
  9. using System.Windows.Documents;  
  10. using System.Windows.Input;  
  11. using System.Windows.Media;  
  12. using System.Windows.Media.Imaging;  
  13. using System.Windows.Navigation;  
  14. using System.Windows.Shapes;  
  15.   
  16. namespace PracticeProject.Views  
  17. {  
  18.     /// <summary>  
  19.     /// Interaction logic for MainView.xaml  
  20.     /// </summary>  
  21.     public partial class MainView : UserControl  
  22.     {  
  23.         public MainView()  
  24.         {  
  25.             InitializeComponent();  
  26.             DataContext = new ViewModels.ViewModelClass();  
  27.         }  
  28.     }  
  29. }  
Finally, the View's XAML code. This is honestly the hardest part about using the MVVM pattern. We first declare the ViewModel in a namespace of the XAML document. We create a Listbox and bind the Movies ObservableCollection to it. We then set the UpdateSourceTrigger to PropertyChanged. Lastly, we set the DisplayMemberPath to Name. Make sure IsSynchronizedWithCurrentItem is set to true.

Next, we create a stackPanel and will set the DataContext of it to be to the ListBox with the Path set as the selected item.

We do this to ensure that any item that is selected within the listbox will force the bound objects to update accordingly.

We will now create a label and TextBox within the stackpanel and bind the text of the TextBox to Genre and the context of the label to ReleaseDate.
  1. <UserControl x:Class="PracticeProject.Views.MainView"  
  2.              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"  
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"  
  4.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"  
  5.              xmlns:d="http://schemas.microsoft.com/expression/blend/2008"  
  6.              xmlns:local="clr-namespace:PracticeProject.Views"  
  7.              mc:Ignorable="d"  
  8.              xmlns:vm="clr-namespace:PracticeProject.ViewModels"  
  9.              d:DesignHeight="300" d:DesignWidth="300">  
  10.     <Grid>  
  11.         <ListBox x:Name="listBox" ItemsSource="{Binding Movies, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Name" Height="100" IsSynchronizedWithCurrentItem="True"/>  
  12.         <StackPanel Margin="10" VerticalAlignment="Bottom" DataContext="{Binding ElementName=listBox, Path=SelectedItem}">  
  13.             <Label x:Name="label" Content="{Binding ReleaseDate}" Height="36"/>  
  14.             <TextBox x:Name="textBox" Height="34" TextWrapping="Wrap" Text="{Binding Genre}" IsReadOnly="True"/>  
  15.         </StackPanel>  
  16.     </Grid>  
  17. </UserControl>  
Now, you can run the program and any item you select within the Listbox will update with the corresponding values within the label and TextBox.

Points of Interest

Once you get the hang of the basics of the MVVM pattern, you will be able to extend it further by learning the ICommand Interface.

Acknowledgements

It honestly took me several months to fully understand how the MVVM pattern works and I couldn't have done it without the help of people from StackOverflow, CodeProject, YouTube and the MSDN forums. So, in this section I would like to issue my sincerest thanks to all of the individuals responsible in helping me and others. There are too many people and sources to name, so if you are an individual that took time out to answer my questions, make tutorials such as mine, or even have made video tutorials, all of you have my sincerest thanks for helping other developers such as myself.


Similar Articles