Click here to Skip to main content
15,886,362 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 
Hi Jesse,

Thanks for posting your Code and "tutorial" here. When I read your article some "thoughts" came to my mind...
Shure I could have ingored them, but maybe it's better to share them with you Wink | ;)

1: A Barebones Implementation:

Basic MVVM-implementation consist of two things: A baseclass to handle change-notification (you don't want to repeat the code for each ViewModel class)and a ICommand implemenation to handle user-Input.
E.g. I'm writing large EnterpriseApplications with the MVVM pattern - I implemented those two (not Basic, but realworld), and didn't find any need for a MVVM-Framework until now. So this is what I'd call "barebones". I don't see either of these in your code....
  1. Real benefit comes with Technology-Independence
Most tutorials (also yours) are ignoring the fact that all the advantages of MVVM, can be reached with other patterns (this was done all the years I'm in SW-development with changing names). Most essential reason for me to use MVVM, is it's UI Technology Independence - then a "barebones implementation" has also abstract all the common UI-Patterns (like Dialogs) - so here is where the Frameworks come in - a lot of work if you want to do it yourself.
If you use MVVM in a UI-dependend way, it is no problem, but in my opinion it contradicts the most important reason to use it in the first-place - To have the ViewModel as a reusable-building block for any application. In an ideal world one ViewModel supports 10 different Clients with different UI-tech... (Web, Phone, WPF, UWP).
  1. Missunderstanding what is the Model and what is the ViewModel.
I think you got a big missunderstanding here (quite common with the pattern) What you say about the Model is true for the ViewModel and vice versa.
Let's sum up what A ViewModel is:
* Handles ChangeNotification (two way) - if you have a Model that also provides this (by INotifyPropertyChanged, Change-Events, whatever) it's nice, but normally you wont see this on Model classes, or you can not add it because you don't own the code of the model... ( very realstic and common scenario)
* presents Model-Data in a way a UI can use it. So if you have as example a GUID-typed variable in a model you may present it as string on the ViewModel.
* Presents UI-State (selection, focus, ...) in an UI-tech-independend way - something a Model will never do
* Relays commands from the view to the underlaying model or executes the commands. - you will hardly see any ICommand support on model classes.

So you see - the ViewModel is the glue between the view and the model. Just think about all the (normal) cases where you won't control the Model-Code... Just think about a ViewModel as a kind of Adapter (-pattern) for Model-classes. So that's it what a ViewModel should do: Notify, Relay, Encapsulate (the Model).

There will be cases (you often see this in simple tutorials) where there is no need for a "model" becase all the Information is allready contained in the ViewModel. I think this tutorials a the reasons for your confusion (and for many others...).

I won't go into "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" - Just a big NOOO it is not! this is what "Model" code will do - run your System in real (e.b. Change data, call Service whatever)!

I hope you take my "critics" in a positive way. I'm not saying that all my thoughts are gold. But I have some years of experience now with the MVVM pattern and use it every day...

Kind regards

Johannes
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.