Click here to Skip to main content
15,887,837 members
Articles / Desktop Programming / WPF

A Barebones Implementation of the MVVM Pattern

Rate me:
Please Sign up or sign in to vote.
4.85/5 (15 votes)
31 Jul 2015CPOL8 min read 25.7K   464   26   12
Breaking down the MVVM pattern

Overview:

There is an extremely vast array of tutorials over the internet on learning the MVVM pattern and sadly, in my opinion, many 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 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.
What I mean by the basic implementation of the MVVM pattern is, I will not be utilizing the ICommand Interface, nor will I be using an external library such as MVVMLight. The only required thing will be the INotifyPropertyChanged Interface.
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. My code written below was written in .Net 4.5.2 and also tested with .Net 4.6 to ensure stability with the release of Visual Studio 2015, so that this article could be the most up to date as possible.

Without further adeu, Let’s get started with Section 1.

Section 1:

The MVVM pattern is an extension on the MVC pattern that is mainly used in Web development. Instead of Model View Controller, it features a Model, a View and ViewModel. So, if you are a beginner on 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 are the Benefits of the MVVM pattern?
1.    Your UX designer and a Backend programmer can work on the same project without bumping heads.
2.    It is easy to create Unit tests for the ViewModel and the Model without the View.
3.    Easy to redesign the UI that doesn’t affect your Backend code.
4.    It is easier to integrate an existing business logic into an MVVM solution.
5.    Easier to maintain and update
6.    Less code you have to write in the long run

What does each portion of the MVVM model mean and do?
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. 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.

How does MVVM work?
The model class acts as the basis for your data. It holds the information you want to portray in your application. The viewmodel acts as the glue between your data and your UI. And your View is your UI.

Why is DataBinding 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.

What does DataBinding do?
This is by no means everything that databinding can do, it is more of a brief overview.
Databinding connects two properties together, if one changes, the other will as well. There are many ways to do this, such as what I do in Section 2. What I do in Section 2 is utilize the PropertyChanged event, the other method is a Dependency property.

Dependency Property versus PropertyChanged Event:
There are several differences between Dependency Properties and PropertyChanged Events.
Dependency Objects are not marked serializable, have thread affinity (which means it can only be accessed on the thread in which it was created, and overrides and seals the Equals() and GetHashCode() methods.
However, in testing, Dependency Objects perform much better than NotifyPropertyChanged. If you are interest in the findings of the test, another Article has been written about the subject in detail. (http://www.codeproject.com/Articles/62158/DependencyProperties-or-INotifyPropertyChanged)


 What technologies can utilize the MVVM pattern?
It should be noted that it is not a requirement to use the MVVM pattern with these technologies.
It is acceptable to use MVVM with web technologies such as JavaScript or ASP.NET, however, there is a requirement. If you are making a rich UI application for a web solution, you can use MVVM. Windows Phone 7, Windows Phone 8, Windows Phone 8.1, Windows Metro Applications (8 and 8.1), and Windows 10 Universal Projects are all exceptional candidates for using the MVVM pattern. If you are a developer that still uses the deprecated Silverlight, MVVM is also great there. The most notable however, is a Windows Desktop WPF application is generally where most people start to learn the MVVM pattern. I have also seen instances where people use MVVM with a Unity project.

Why should I learn the MVVM pattern?
I personally feel that if you develop using technologies that have a way for you to implement it, that you should learn it because it will be that much easier for you in the long run. What I mean by that is, if you have a colleague that implements it in a project for your job or a prospective client requires you to implement the pattern for their project then it would be very much advantageous for you to know it and understand at least how it works.


How do you use DataBinding?
In XAML, databinding is very simple to do. Consider the snippet below.

C#
<TextBox x:Name="textBox" Height="34" TextWrapping="Wrap" Text="{Binding Genre}" IsReadOnly="True"/>

What this XAML snippet is telling us is that, The textbox's text is set to the Bound path of Genre.
Now, what if you wanted to write the code using C# instead of using XAML? Well, consider the snippet below.

C#
BindingSource binding = new BindingSource();
binding.Add(new Models.ModelClass("Action");
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.

C#
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

namespace PracticeProject.Models
{
    public class ModelClass : INotifyPropertyChanged
    {
        private string name;
        public string Name
        {
            get { return name; }
            set
            {
                name = value;
                NotifyPropertyChanged();
            }
        }
        private string releaseDate;
        public string ReleaseDate
        {
            get { return releaseDate; }
            set
            {
                releaseDate = value;
                NotifyPropertyChanged();
            }
        }
        private string genre;
        public string Genre
        {
            get { return genre; }
            set
            {
                genre = value;
                NotifyPropertyChanged();
            }
        }

        public event PropertyChangedEventHandler PropertyChanged;
        private void NotifyPropertyChanged([CallerMemberName] String propertyName = "")
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

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.

C#
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using System.Xml.Linq;
using System.IO;
using System.Reflection;
using System.Windows;
namespace PracticeProject.ViewModels
{
    public class ViewModelClass
    {
        public ObservableCollection<Models.ModelClass> Movies { get; set; }
        StreamReader _textStreamReader;
        public ViewModelClass()
        {
           LoadEmbeddedResource("PracticeProject.DataSources.Movies.xml");
            XDocument xdoc = XDocument.Load(_textStreamReader);
            var movies = xdoc.Descendants("Movies")
                .Select(x =>
                new Models.ModelClass
                {
                    Name = (string)x.Element("Name"),
                    Genre = (string)x.Element("Genre").Value,
                    ReleaseDate = (string)x.Element("ReleaseDate").Value
                }
                ).ToList();
            Movies = new ObservableCollection<Models.ModelClass>(movies);
        }
        private void LoadEmbeddedResource(string resource)
        {
            try
            {
                Assembly _assembly;
                _assembly = Assembly.GetExecutingAssembly();
                _textStreamReader = new StreamReader(_assembly.GetManifestResourceStream(resource));
            }
            catch (Exception ex)
            {
                MessageBox.Show("Error Loading Embedded Resource: " + ex, "Error!", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }
    }
}

 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 shown below.

C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace PracticeProject.Views
{
    /// <summary>
    /// Interaction logic for MainView.xaml
    /// </summary>
    public partial class MainView : UserControl
    {
        public MainView()
        {
            InitializeComponent();
            DataContext = new ViewModels.ViewModelClass();
        }
    }
}

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 we set the DataContext of it to be to the ListBox with the Path set as 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 now will create a label and textbox within the stackpanel, we will bind the text of the textbox to Genre and the context of the label to ReleaseDate.

C#
<UserControl x:Class="PracticeProject.Views.MainView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
             xmlns:local="clr-namespace:PracticeProject.Views"
             mc:Ignorable="d"
             xmlns:vm="clr-namespace:PracticeProject.ViewModels"
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <ListBox x:Name="listBox" ItemsSource="{Binding Movies, UpdateSourceTrigger=PropertyChanged}" DisplayMemberPath="Name" Height="100" IsSynchronizedWithCurrentItem="True"/>
        <StackPanel Margin="10" VerticalAlignment="Bottom" DataContext="{Binding ElementName=listBox, Path=SelectedItem}">
            <Label x:Name="label" Content="{Binding ReleaseDate}" Height="36"/>
            <TextBox x:Name="textBox" Height="34" TextWrapping="Wrap" Text="{Binding Genre}" IsReadOnly="True"/>
        </StackPanel>
    </Grid>
</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 or implement using an external library such as MVVMLight.
There are many additional things that you can do with the MVVM pattern that is not discussed in this article.
 

Acknowledgements

It honestly took me several months to fully understand how the MVVM pattern works and I couldn't have done it without help from 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.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Junior)
United States United States
I am a self study student and practitioner of the wonderful world of software development using the language of C#.

Comments and Discussions

 
GeneralMy vote of 2 Pin
johannesnestler11-Oct-17 2:52
johannesnestler11-Oct-17 2:52 
QuestionThoughts Pin
johannesnestler11-Oct-17 2:50
johannesnestler11-Oct-17 2:50 
QuestionThanks for sharing Pin
HLLau864-Oct-15 19:02
HLLau864-Oct-15 19:02 
QuestionNo Datacontext code needed in MainView.cs Pin
Member 118233243-Aug-15 15:29
Member 118233243-Aug-15 15:29 
AnswerRe: No Datacontext code needed in MainView.cs Pin
Jesse Glover3-Aug-15 18:59
Jesse Glover3-Aug-15 18:59 
QuestionCrystal Clear Pin
Mohamed Mortada3-Aug-15 7:41
Mohamed Mortada3-Aug-15 7:41 
AnswerRe: Crystal Clear Pin
Jesse Glover3-Aug-15 10:51
Jesse Glover3-Aug-15 10:51 
QuestionGood Article Pin
Greg Osborne3-Aug-15 6:24
Greg Osborne3-Aug-15 6:24 
AnswerRe: Good Article Pin
Jesse Glover3-Aug-15 10:49
Jesse Glover3-Aug-15 10:49 
Questiongood content Pin
jefersonfnd31-Jul-15 9:44
jefersonfnd31-Jul-15 9:44 
AnswerRe: good content Pin
Jesse Glover31-Jul-15 11:22
Jesse Glover31-Jul-15 11:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.