jump to navigation

An introduction to MVVM pattern using WPF July 17, 2011

Posted by fofo in C#, c# 4.0, Visual Studio 2010, WPF.
Tags: , ,
trackback

In this post I will show you how to build a simple WPF Application using the popular and well know MVVM (Model View View Model) pattern.

I assume that you know the basics of XAML,WPF. I am going to use a hands-one example using Visual Studio and 2010.

Before we go on and begin with our example I must say a few things about MVVM.Make a note that we can use this pattern when building Silverlight applications as well.

So what is MVVM? In a nutshell it is a UI Design Pattern. You do not have to explore too many things or spend too much time studying this pattern before start using it.

A pattern is a documented solution to a specific software problem. So MVVM being a pattern,  is a set of guidelines that makes it much easier to write WPF applications.

It is based on a very important software principle called seperation of concerns.By building WPF applications using MVMV we have solid maintainable code.

By breaking apart our application, enables us to do UI testing.

On top of that we have applications that ( that are built with MVVM ) are much more maintenable and extensible. We keep the designers and the developers happy!!!! Each of them can focus on their tasks and noone interferes with each other’s work.

Let’s have a closer look on the main components of MVVM pattern. Have a look at the picture below.It gives a high level overview of the pattern.

MVVM Pattern

MVVM Pattern

The Model has no reference to the View or the ViewModel . It does not or care about the existence of the View or the Model.

The Model is that data. It could be an xml file or a data access layer (e.g EF). It could be a custom object(s) representing a part of our domain.

The View does not have a reference to the Model. A View is defined in XAML and should not have any logic in the code-behind. It binds to the ViewModel by only using data binding.
The ViewModel can be thought of as an abstraction of the View. It provides enough information about the Model data points that the View can use for data-binding. It contains Commands the View can use to interact with the Model. The ViewModel has a reference to the Model.

Let’s start with our hands on example.I will create a simple WPF application

1) Launch Visual Studio 2010 (any edition will do). Choose C# as the development language and WPF Application from the available templates.

2) Choose a suitable name for your application. I have named it “WpfMVVM”

3) Add 3 folders in your solution with the names View,Model,ViewModel.

4) I will use a custom object to store the data so I will add a new class to the Model folder. I will name it Footballer.cs ( yes, we will save and display footballer names ). I will add some properties on this class like  firstname,lastname,age,height,weight and another little property called SavedTime so I know when the data was last updated. So the first version of the Footballer class follows.

   class Footballer
    {

        private string _firstname;

        public string FirstName
        {
            get { return _firstname; }
            set
            {
                _firstname = value;

            }
        }

        private string _lastname;

        public string LastName
        {
            get { return _lastname; }
            set
            {

                _lastname = value;

            }
        }

        private int _age;

        public int Age
        {
            get { return _age; }
            set
            {
                _age = value;

            }
        }

        private double _height;

        public double Height
        {
            get { return _height; }
            set
            {
                _height = value;

            }
        }

        private double _weight;

        public double Weight
        {
            get { return _weight; }
            set
            {
                _weight = value;

            }
        }

        private DateTime _SavedTime;

        public DateTime SavedTime
        {
            get { return _SavedTime; }
            set
            {
                _SavedTime = value;

            }
        }

}

Then I need to notify my UI (View) that some of these properties changed. I do that by implementing the INotifyPropertyChanged interface.

Now the View is notified when there changes in the property values,since when that happens notifications are fired. This allows the View to display any changes that have been made in the object’s underlying properties. The second version of the Footballer class follows


class Footballer:INotifyPropertyChanged
{

private string _firstname;

public string FirstName
{
get { return _firstname; }
set
{
_firstname = value;
OnPropertyChanged("FirstName");

}
}

private string _lastname;

public string LastName
{
get { return _lastname; }
set
{

_lastname = value;
OnPropertyChanged("LastName");
}
}

private int _age;

public int Age
{
get { return _age; }
set
{
_age = value;
OnPropertyChanged("Age");
}
}

private double _height;

public double Height
{
get { return _height; }
set
{
_height = value;
OnPropertyChanged("Height");
}
}

private double _weight;

public double Weight
{
get { return _weight; }
set
{
_weight = value;
OnPropertyChanged("Weight");
}
}

private DateTime _SavedTime;

public DateTime SavedTime
{
get { return _SavedTime; }
set
{
_SavedTime = value;
OnPropertyChanged("SavedTime");
}
}

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string property)
{
if (PropertyChanged !=null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}

}

}

If I want to implement data validation logic, the Model class is a good place to do it.In this case I need to implement the IDataErrorInfo interface.In this example I will add some validation for the fields “FirstName”, “Lastname”. These fields cannot be empty.

The third version of the Footballer class follows


class Footballer:INotifyPropertyChanged,IDataErrorInfo
{

private string _firstname;

public string FirstName
{
get { return _firstname; }
set
{
_firstname = value;
OnPropertyChanged("FirstName");

}
}

private string _lastname;

public string LastName
{
get { return _lastname; }
set
{

_lastname = value;
OnPropertyChanged("LastName");
}
}

private int _age;

public int Age
{
get { return _age; }
set
{
_age = value;
OnPropertyChanged("Age");
}
}

private double _height;

public double Height
{
get { return _height; }
set
{
_height = value;
OnPropertyChanged("Height");
}
}

private double _weight;

public double Weight
{
get { return _weight; }
set
{
_weight = value;
OnPropertyChanged("Weight");
}
}

private DateTime _SavedTime;

public DateTime SavedTime
{
get { return _SavedTime; }
set
{
_SavedTime = value;
OnPropertyChanged("SavedTime");
}
}

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string property)
{
if (PropertyChanged !=null)
{
PropertyChanged(this, new PropertyChangedEventArgs(property));
}

}

public string Error
{
get { return null; }
}

public string this[string columnName]
{
get

{
string theerror = string.Empty;

if ((string.IsNullOrEmpty (_firstname)))
{
theerror = "This field is required";
}

else if ((string.IsNullOrEmpty(_lastname)))
{
theerror = "This field is required";
}
return theerror;
}
}

}

We will have to make some changes to the XAML (Set the ValidatesOnDataErrors=True for firstname and lastname elements) for this to work but I will show you later.

Νow let’s move to the ViewModel implementation. This model must have properties that expose instances of the Model objects.

So in this case we must have a property in the ViewModel class that exposes the Footballer class that lives in the Model.

Add a new item to your project, a class file, name it FootballerViewModel.cs

The first thing I need to do in my new class is to implement the INotifyPropertyChanged interface.This is because the View is bound to the ViewModel. INotifyPropertyChanged interface is the way to push data to the View.

The first version of the ViewModel class follows

class FootballerViewModel:INotifyPropertyChanged
{

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

}
}

Let’s create a property that  is an instance of the Model object .The second version of the ViewModelclass follows

class FootballerViewModel:INotifyPropertyChanged
{

private Footballer _myfootballer;

public Footballer MyFootballer
{
get { return _myfootballer; }
set

{

_myfootballer = value;
OnPropertyChanged("MyFootballer");

}
}

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

}
}

Now I will use the constructor for the ViewModel class and populate it with some random data.

The third version of the ViewModel follows


class FootballerViewModel:INotifyPropertyChanged
{

public FootballerViewModel()
{
LoadFootballers();
}

private void LoadFootballers()
{
MyFootballer  = new Footballer()
{
FirstName = "Steven",
LastName = "Gerrard",
Age = 31,
Weight = 88.6,
Height = 1.84

};
}

private Footballer _myfootballer;

public Footballer MyFootballer
{
get { return _myfootballer; }
set

{

_myfootballer = value;
OnPropertyChanged("MyFootballer");

}
}

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

}
}

Now, let’s create the View. The View will be purely XAML. It consists of the visual elements like buttons,textboxes. It is not responsible for retrieving data,implement business logic or validation logic.

First things first. Move the MainWindow.xaml file to the View folder.

Go to the App.xaml file and change the StartupUri attribute of the Application element to StartupUri=”View/MainWindow.xaml”


<Window x:Class="WpfMVVM.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" >

<Grid>

<Grid.RowDefinitions>
<RowDefinition Height="46*" />
<RowDefinition Height="46*" />
<RowDefinition Height="46*" />
<RowDefinition Height="46*" />
<RowDefinition Height="46*" />
<RowDefinition Height="46*" />
<RowDefinition Height="46*" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="121*" />
<ColumnDefinition Width="382*" />
</Grid.ColumnDefinitions>
<TextBlock Height="23" HorizontalAlignment="Left" Margin="10,12,0,0" Name="textBlock1" Text="First Name:" VerticalAlignment="Top"
Width="82" FontSize="16" />
<TextBox Grid.Column="1" Height="23" HorizontalAlignment="Left" Margin="45,12,0,0" Name="textBox1" VerticalAlignment="Top"
Width="266" />
<TextBlock Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="12,8,0,0" Name="textBlock2" Text="Last Name:"
VerticalAlignment="Top" Width="82" FontSize="16" />
<TextBlock Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="12,9,0,0" Name="textBlock3" Text="Age:"
VerticalAlignment="Top" FontSize="16" />
<TextBlock Grid.Row="3" Height="23" HorizontalAlignment="Left" Margin="10,12,0,0" Name="textBlock4" Text="Height:"
VerticalAlignment="Top" FontSize="16" />
<TextBlock Grid.Row="4" Height="23" HorizontalAlignment="Left" Margin="10,9,0,0" Name="textBlock5" Text="Weight:"
VerticalAlignment="Top" FontSize="16" />
<TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="45,9,0,0" Name="textBox2"
VerticalAlignment="Top" Width="266"  />
<TextBox Grid.Column="1" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="45,9,0,0" Name="textBox3"
VerticalAlignment="Top" Width="266"  />
<TextBox Grid.Column="1" Grid.Row="3" Height="23" HorizontalAlignment="Left" Margin="45,12,0,0" Name="textBox4"
VerticalAlignment="Top" Width="266"  />
<TextBox Grid.Column="1" Grid.Row="4" Height="23" HorizontalAlignment="Left" Margin="45,9,0,0" Name="textBox5"
VerticalAlignment="Top" Width="266"  />
<TextBlock Grid.Row="5" HorizontalAlignment="Left" Margin="12,12,0,13" Name="textBlock6" Text="Time Saved:" FontSize="16" />
<TextBox Grid.Column="1" Grid.Row="5" Height="23" HorizontalAlignment="Left" Margin="45,13,0,0" Name="textBox6"
VerticalAlignment="Top" Width="266" />
<Button Content="Update" Grid.Column="1" Grid.Row="6" Height="24" HorizontalAlignment="Left"
Margin="92,15,0,0" Name="button1" VerticalAlignment="Top" Width="156" FontSize="16" FontFamily="Garamond"
FontWeight="Bold" BorderBrush="#FF407F2E" Foreground="#FFE39223" Background="#FF175D17" />
</Grid>
</Window>

Now let’s make the necessary changes on the View so it can bind to the Model through the ViewModel.

We have first to make a reference to theViewModel class/object so I include the following namespace.

xmlns:football="clr-namespace:WpfMVVM.ViewModel"

This is the first step to hook a View to the ViewModel. We tell WPF where our ViewModel lives.

Then I will create the ViewModel as a resource (static resource).

<Window.Resources>

        <football:FootballerViewModel x:Key="FootballerViewModel" />

</Window.Resources>

Then in the Grid element I make the following change

Grid DataContext="{StaticResource FootballerViewModel}" >

The DataContext property inherits its value to child elements. So you can set the DataContext on a layout container (Grid) and its values are inherited to all child elements. This is very useful in our case where we want to bind to the same data object.

Databinding is typically done in XAML by using the {Binding} markup extension. We have to bind the Text attribute of the TextBox element to the various properties as implemented in the Model through the ViewModel.

<TextBox Grid.Column="1" Height="23" HorizontalAlignment="Left" Margin="45,12,0,0" Name="textBox1"
VerticalAlignment="Top" Width="266" Text="{Binding MyFootballer.FirstName ValidatesOnDataErrors=True}" />

<TextBox Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" Margin="45,9,0,0" Name="textBox2"
VerticalAlignment="Top" Width="266" Text="{Binding MyFootballer.LastName, ValidatesOnDataErrors=True}" />

<TextBox Grid.Column="1" Grid.Row="2" Height="23" HorizontalAlignment="Left" Margin="45,9,0,0" Name="textBox3"
VerticalAlignment="Top" Width="266" Text="{Binding MyFootballer.Age}" />

<TextBox Grid.Column="1" Grid.Row="3" Height="23" HorizontalAlignment="Left" Margin="45,12,0,0" Name="textBox4"
VerticalAlignment="Top" Width="266" Text="{<strong>Binding MyFootballer.Height</strong>}" />

<TextBox Grid.Column="1" Grid.Row="4" Height="23" HorizontalAlignment="Left" Margin="45,9,0,0" Name="textBox5"
VerticalAlignment="Top" Width="266" Text="{Binding MyFootballer.Weight}" />

<TextBox Grid.Column="1" Grid.Row="5" Height="23" HorizontalAlignment="Left" Margin="45,13,0,0" Name="textBox6"
VerticalAlignment="Top" Width="266" Text="{Binding MyFootballer.SavedTime}" />

Run your application and see the values from the domain object appearing in the textboxes.

We do have a button in our UI. We need to update data from the UI and bind the new data to the textboxes.

We need to have a different communnication between the View and the ViewModel. In this case we will use Commands.

First we need to update the XAML.

<Button Content="Update" Grid.Column="1" Grid.Row="6" Height="24" HorizontalAlignment="Left" Margin="92,15,0,0"
Name="button1" VerticalAlignment="Top" Width="156" FontSize="16" FontFamily="Garamond"
FontWeight="Bold" BorderBrush="#FF407F2E" Foreground="#FFE39223" Background="#FF175D17"
Command="{Binding SaveFootballerCommand}" />

So I updated the XAML for the button element by adding the Command=”{Binding SaveFootballerCommand}”

Now we must add some more code in our ViewModel.

public class SaveFootballerCommand:ICommand
{

Action _saveMethod;

public bool CanExecute(object parameter)
{
return true;
}

public event EventHandler CanExecuteChanged;

public void Execute(object parameter)
{
_saveMethod.Invoke();
}
}

I create a new class, SaveFootballerCommand, that has to implement the ICommand interface. Then I define an Action, _saveMethod, which is what is executed when the button is clicked.

The CanExecute tells me if I am allowed to execute the command.Then I create the Execute method and invoke it.

Now we need to create a property in my ViewModel that exposes that command.

private ICommand _SaveFootballerCommand;

public ICommand SaveFootballerCommand
{
get { return _SaveFootballerCommand; }
set
{
_SaveFootballerCommand = value;
OnPropertyChanged("SaveFootballerCommand");

}
}

Now we need to create an instance of the SaveFootballerCommand.

private void FireCommand()
{
SaveFootballerCommand = new SaveFootballerCommand(updateFootballer) ;
}

I place the inside my constructor the FireCommand() method.

public FootballerViewModel()
{
FireCommand();
LoadFootballers();
}

The updateFootballer method is going to be invoked when the command is executed.So I must implement it.

private void updateFootballer()
{

MyFootballer.SavedTime = DateTime.Now;

}

Now I need to create a constructor of the SavePersonCommand class that takes a parameter. The code follows

public SaveFootballerCommand(Action updateFootballer)
{
_saveMethod = updateFootballer;

}

The whole code for the ViewModel class follows

public SaveFootballerCommand(Action updateFootballer)
{
class FootballerViewModel:INotifyPropertyChanged
{

public FootballerViewModel()
{
FireCommand();
LoadFootballers();
}

private void FireCommand()
{
SaveFootballerCommand = new SaveFootballerCommand(updateFootballer) ;
}

private void updateFootballer()
{

MyFootballer.SavedTime = DateTime.Now;

}

private void LoadFootballers()
{
MyFootballer  = new Footballer()
{
FirstName = "Steven",
LastName = "Gerrard",
Age = 31,
Weight = 88.6,
Height = 1.84

};
}

private Footballer _myfootballer;

public Footballer MyFootballer
{
get { return _myfootballer; }
set

{

_myfootballer = value;
OnPropertyChanged("MyFootballer");

}
}

private ICommand _SaveFootballerCommand;

public ICommand SaveFootballerCommand
{
get { return _SaveFootballerCommand; }
set
{
_SaveFootballerCommand = value;
OnPropertyChanged("SaveFootballerCommand");

}
}

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

}
}

}

Run your application and click the button.Note how the date is updated.

Note that we do not have written a single line of code to the MainWindow.xaml.cs file.

Now that we have a clear understanding of what MVVM is and what the different components are, let’s review again the main concepts.

The ViewModel is responsible for the state and behaviour of the View and it acts like the “middle man” between the View and the Model.

It the middle layer and its main job is to send View information to the Model and Model information to the View.

It has no dependency on the View so we can reuse the ViewModel on different Views or even other platforms.

The ViewModel exposes the Model as properties or commands.

In any case it must implement the INotifyPropertyChanged interface.

The View binds to properties in the ViewModel. It does that by setting the DataContext of a View to an instance of the ViewModel object.

The Model is tha data.Simple as that. The Model’s job is to represent the data and has no knowledge of where or how the data will be presented.

By using this pattern we can have the designers in our company designing the Views with xaml using Visual Studio Designer or Blend. The developers in our company can work with the Model and the ViewModel writing the data access code and businnes logic . We reduce the development time.

This is great pattern because we can make our code more testable and maintainable.

If you want to have a look at the MVVM more closely have a look here.

It would be nice if you could spare some time and have a  look at these related patterns with MVVM pattern like MVP,MVC,PM.

Hope it helps!!! Email me if you need the source code.

About these ads

Comments»

1. Mark - August 9, 2011

Great article for those just getting going on MVVM.

One question though, in the view model you expose the Myfootballer model and bind on the view using it’s properties ;Myfootballer.FirstName, Myfootballer.LastName etc.

Is this the preferred method? Or could the view model expose these properties directly as strings and have the view bind to these?

Are there any benefits to either of these approaches?

Thanks, Mark

2. kayal - April 2, 2012

Hi,
I’m new to MVVM. kindly send me the source of this example.

3. Umasankar - June 29, 2012

Its very userful for a clear picture on MVVM Usage. could you send me the source code please

4. Manik - July 26, 2012

Please send me the source code.

5. Ana - November 8, 2012

Hi ,Excellent article for a beginners like me but implementation of FireCommand didn’t work for me. I followed the example till the end and now am stuck there.Can you please send me the source code?

6. Ajay - December 20, 2012

It is an excellent article. I followed the same steps to do in Win Rt environment and had to add an interface to talk to the VM. Also ViewModel class is not very clear, so I put the code in the following manner:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using FootBaller.Model;

namespace FootBaller.ViewModel
{
public class FootballerViewModel : INotifyPropertyChanged
{
public FootballerViewModel()
{
FireCommand();
LoadFootballers();
}
private Footballer _myfootballer = null;
public Footballer MyFootballer
{
get
{
return _myfootballer;
}

set
{
_myfootballer = value;
OnPropertyChanged(“MyFootballer”);
}
}

private ICommand _SaveFootballerCommand;

public ICommand SaveFootballerCommand
{
get { return _SaveFootballerCommand; }
set
{
_SaveFootballerCommand = value;
OnPropertyChanged(“SaveFootballerCommand”);

}
}

public event PropertyChangedEventHandler PropertyChanged;

public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

}
private void LoadFootballers()
{
MyFootballer = new Footballer()
{
FirstName = “Steven”,
LastName = “Gerrard”,
Age = 31,
Weight = 88.6,
Height = 1.84

};
}
private void updateFootballer()
{

MyFootballer.SavedTime = DateTime.Now;

}
private void FireCommand()
{
SaveFootballerCommand = new SaveFootballerCommand (updateFootballer);
}

}

}

To make the SaveFootballerCommand to work from VM, I added a constructor to SaveFootballerCommand class, and following is the code I got working:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;

namespace FootBaller.ViewModel
{
public class SaveFootballerCommand : ICommand
{
Action _saveMethod;

public SaveFootballerCommand(Action actM)
{
_saveMethod = actM;
}

public bool CanExecute(object parameter)
{
return true;
}

public event EventHandler CanExecuteChanged;

public void Execute(object parameter)
{
_saveMethod.Invoke();
}

}
}

It was an easy implementation for command to work, nice work again.

7. Priyanka - January 3, 2013

hey, this is a very nice article for the beginners. Can you please send me the source code.

8. giovanni poidomani - January 17, 2013

I need a source thanks

9. Richs - February 26, 2013

Can you please send the source code of this article

10. sachin - March 7, 2013

Hi, its nice article. Please send me the source code

11. Going to www.amazon.com - April 25, 2013

Hi there, of course this paragraph is truly nice and I have learned lot of things from it
on the topic of blogging. thanks.

12. raman - June 7, 2013

Please email me source code

13. Priom - July 31, 2013

great tutorial, please send me the code, priombiswas@yahoo.com

14. Krithiga - September 19, 2013

Awesome article on MVVM. Thank u so much for the explanations. Please do send me the code

15. tripurary - October 18, 2013

Hi,
I’m new to MVVM. kindly send me the source of this example.

Hoa - November 21, 2013

it’s very nice article. Please send me the source code.
Thanks

16. Hoa - November 21, 2013

it’s very nice article. Please send me the source code.
Thanks

17. sanjeev - January 31, 2014

nice article keep it thanks

18. sanjeev - January 31, 2014

kindly sent me the source code

19. Omar Carrillo - January 31, 2014

it’s very nice article. Please send me the source code.
Thanks

blackdeath_166@hotmail.com


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

Follow

Get every new post delivered to your Inbox.

Join 1,788 other followers

%d bloggers like this: