MVVM (Model View View-Model) For Dummies/Simplified

Introduction

A few months ago I took the leap from WinForms programming to WPF and quite naturally, I took to it like a duck to water. Well, to be honest I had been developing Silverlight applications since its inception and being that Silverlight is a subset of WPF it required a low learning curve to catch on. However, the concept of Commanding was a bit different in WPF and I soon began to see how much more powerful Commanding in WPF was compared to Silverlight.

One of the areas in which Commanding is exemplary is in the way in which it complements MVVM.  But what is MVVM, and why is it useful? This is the toughest concept (In my opinion) to grasp when it comes to WPF (and Silverlight) programming. Why you ask? Because it is simple and as developers we often like code or concepts that warp our minds, so when we figure it out we can brag to our peers how it only took 2 hours to understand and implement the next BIG thing (No I am not projecting).  On a side not, I have found that everyone one who blogs about MVVM complicate it by adding too much code which just throws you for a loop. Simplicity is the key to all things complicated. So let’s delve into a little theory and we will finish up with some short-to-the-point code.

Purpose

The purpose of this post is to

a. Give a simple and clear definition of Model View View-Model

b. Provide a clear and simple sample that clearly illustrates MVVM usage

MVVM?

Figure 1.

MVVM - Model View ViewModel

MVVM - Model View ViewModel

Just in case you cannot read the text in the image here it is below:

  1. The View holds a reference to the ViewModel. The View basically displays stuff by Binding to entities in the View Model.
  2. The ViewModel exposes Commands, Notifiable Properties, and Observable Collections to the View. The View Binds to these ViewModel entities/members
  3. The Model is your data and or application objects that move data while applying Application Logic. If you have a Business Layer then you might not need this.

Above is a simple figure that tells you exactly what MVVM is. In my own words, the ViewModel is the most significant in the entire pattern as it is the glue that sits between the View and the Model and binds both of them together. Now let’s explore some code.

Code

The application you are about to see is very intricate in design and implementation and as such must not be criticized by anyone. Here is an overview of what the application does. It takes your first name, last name and age and displays it to you in message box.  Below is the really complicated class diagram.

Figure 2.

MVVM - Class Diagram

MVVM - Class Diagram

Let’s take a look at the PersonModel class which is the only Model in the application:


namespace OliverCode.MVVM.Model
{
internal class PersonModel : System.ComponentModel.INotifyPropertyChanged
{
private string firstName;
public string FirstName
{
get { return firstName; }
set
{
if(firstname != value)
{
firstName = value;
OnPropertyChanged("FirstName");
}
}
}
private string lastName;
public string LastName
{
get { return lastName; }
set
{
//Check ensures you do not update unchanged values
if(lastname != value)
{
lastName = value;
OnPropertyChanged("LastName");
}
}
}
private int age;
public int Age
{
get { return age; }
set
{
if(age != value)
{
age = value;
OnPropertyChanged("Age");
}
}
}
#region INotifyPropertyChanged Members
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
#endregion
}
}

Person class implements the INotifyPropertyChanged interface which enables a WPF elements to be immediately notified if any of the properties changed on a Person object.

Moving on… Let’s look at the View which is cleverly named, PersonView (Quite creative if I might add).


<UserControl x:Class="OliverCode.MVVM.View.PersonView"

    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

    Height="Auto" Width="Auto"

    xmlns:local="clr-namespace:OliverCode.MVVM.ViewModel">

    <StackPanel Orientation="Vertical" Margin="4">

        <!--Here is where we the view gets a reference to the ViewModel Declaratively-->

        <StackPanel.DataContext>

            <local:PersonViewModel />

        </StackPanel.DataContext>

        <StackPanel Orientation="Vertical" DataContext="{Binding Path=Person, Mode=TwoWay}" Margin="4">

            <StackPanel Orientation="Horizontal">

                <Label Content="First Name:" Margin="0,0,4,0"/>

                <TextBox Width="250" Text="{Binding Path=FirstName}"/>

            </StackPanel>

            <StackPanel Orientation="Horizontal" Margin="0,5,0,0">

                <Label Content="Last Name:" Margin="0,0,4,0"/>

                <TextBox Width="250" Text="{Binding Path=LastName}"/>

            </StackPanel>

            <StackPanel Orientation="Horizontal" Margin="0,5,0,0">

                <Label Content="Age:" Margin="35,0,4,0"/>

                <TextBox Width="50" MaxLength="3" Text="{Binding Path=Age}"/>

            </StackPanel>

        </StackPanel>

        <StackPanel>

        <!—The Command is bound to the Property in the PersonViewModel call SavePersonCommand-->

            <Button Content="Save" HorizontalAlignment="Right" Width="80" Command="{Binding Path=SavePersonCommand}"/>

        </StackPanel>

    </StackPanel>

</UserControl>

The key take away from the XAML above is the way the PersonViewModel is attached to the PersonView’s DataContext (This is the typical means by which the View gets a reference to the ViewModel).  Also pay attention to the Button element who’s Command is using the Binding Class to Attach the SavepersonCommand, which is a property on the ViewModel. Typically, binding to a command is more complicated than this, but because of the WPF Mvvm Toolkit 1.0 which is located here http://wpf.codeplex.com/Wiki/View.aspx?title=WPF%20Model-View-ViewModel%20Toolkit from the Microsoft Team, developers can now easily Bind to commands. I have included the DelegateCommand class in the project so you don’t need to download it directly. There is also a CommandReference class whose purpose is to resolve limitations in WPF when binding data binding from XMAL (This is not used in the program).

WPF Mvvm Toolkit 1.0 Tidbits

There are several classes in the toolkit but the one you should pay attention to is the DelegateCommand. This class makes it easy to write a function to handle a gesture or command. Gestures can be thought of as any interaction that can initiate a command. I use the DelegateCommand directly in my PersonViewModel like so.


private DelegateCommand savePersonCommand;

public ICommand SavePersonCommand
{
get
{
if(savePersonCommand == null)
savePersonCommand = new DelegateCommand(new Action(SaveExecuted), new Func<bool>(SaveCanExecute));
return savePersonCommand;
}
}
public bool SaveCanExecute()
{
return Person.Age > 0 && !string.IsNullOrEmpty(Person.FirstName) && !string.IsNullOrEmpty(Person.LastName);
}
public void SaveExecuted()
{
System.Windows.MessageBox.Show(string.Format("Saved: {0} {1} - ({2})", Person.FirstName, Person.LastName, Person.Age));
}

Here is the entire personViewModel class:

namespace OliverCode.MVVM.ViewModel
{
internal class PersonViewModel
{
public PersonModel Person { get; set; }
private DelegateCommand savePersonCommand;
public ICommand SavePersonCommand
{
get
{
if(savePersonCommand == null)
savePersonCommand = new DelegateCommand(new Action(SaveExecuted), new Func<bool>(SaveCanExecute));
return savePersonCommand;
}
}
public PersonViewModel()
{
//This data will load as the default person from the model attached to the view
Person = new PersonModel { FirstName = "John", LastName = "Doe", Age = 999 };
}
public bool SaveCanExecute()
{
return Person.Age > 0 && !string.IsNullOrEmpty(Person.FirstName) && !string.IsNullOrEmpty(Person.LastName);
}
public void SaveExecuted()
{
System.Windows.MessageBox.Show(string.Format("Saved: {0} {1} - ({2})", Person.FirstName, Person.LastName, Person.Age));
}
}
}

Simple, isn’t it? I hope I have helped someone by saving them hours trying to find a simple demonstration of MVVM in WPF. Thank you now go code.

Advertisements

7 thoughts on “MVVM (Model View View-Model) For Dummies/Simplified

  1. I can’t thank you enough for this great explanation. Truly a work of art the way you simplified the pattern. I already passed on the knowledge to my team and have made sure everyone to bookmark your blog.

    Thank you very much Alfie

  2. sry, but you didn’t get it.

    The picture is excellent, but the execution is not.

    Your model implements UI logic. What I mean is the INotifyChanged. This should be implemented on the view model to achieve true separation of concerns.

    Also the reference to the actual model object inside the view model should be private. Its not supposed to be access from the outside anymore.

  3. Excellent, simple explanation. Thank you!! Looked at many others, and have been no further on!! But have a solid basic understanding now.

  4. Good, clear explanation. Thanks.

    Hi, I see that you expose a public get/set of the Model in your ViewModel. Do you think this is good practice? I would be concerned about others mishandling this and decoupling the Model from the ViewModel.

    • Patrick, you are correct, I do not have to let the PersonModel be public, but if I did not have the PersonModel public then I would have to write Public Fields in the ViewModel for each UI field that would map to the PersonModel’s properties and I would have to let them all participate in the “notify property changed”.

      I would also have to implement a setter and getter for each field that the Model would want to expose in the ViewModel, which is repeating the work that is already done by the PersonModel. The one thing I would change is that I would make the setter private on the Person property. having it public opens it up to someone else changing the model outside of the ViewModel, which I think is a violation of MVVM due to the fact that a ViewModel is the sole representative of the Model that should act on the Model’s behalf..

      Ask yourself, if you had a View hat had say 10 Models to deal with and each Model had roughly 5 fields that the View must present to a user – from a maintenance point of view, would you want to be the programmer that had to deal with the ViewModel that housed all the fields when they have to change?

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s