How to Implement MVVM, INotifyChanged and ICommand in a Silverlight Application

In this post we will be converting an application that adds two numbers together to use the MVVM (Model-View-ViewModel) pattern as part of the How To Refactor And Build Better Microsoft Silverlight Applications series.

The code used in this post can be downloaded here.

Why MVVM?

While I could write about what MVVM is, I would just be repeating what Josh Smith and Jesse Liberty have already covered in the ‘WPF Apps With The Model-View-ViewModel Design Pattern’ MSDN article and the ‘MVVM – It’s Not Kool-Aid*’ blog post.

I like the MVVM pattern because it helps me to write code and develop solutions that:

  • keeps my code behind files as code free as possible
  • can be unit tested
  • are simpler to read and understand
  • are less headache to maintain
  • adhere to good programming principles
  • make validation easier to implement

It’s important to remember MVVM isn’t the solution to every problem. If you don’t need to use it, don’t, do whatever is right for your application.

The application pre MVVM

In the current application the XAML looks like this

    <Grid x:Name="LayoutRoot" Background="White" Height="100" Width="350">
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
            <ColumnDefinition/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
        </Grid.RowDefinitions>
        <TextBox Grid.Column="0" Text="0" Height="25" TextAlignment="Right" x:Name="tbFirstValue"/>
        <TextBlock Grid.Column="1" Text="+" Height="25" TextAlignment="Center"/>
        <TextBox Grid.Column="2" Text="0" Height="25" TextAlignment="Right" x:Name="tbSecondValue"/>
        <TextBlock Grid.Column="3" Text="=" Height="25" TextAlignment="Center"/>
        <TextBlock Grid.Column="4" Text="0" Height="25" TextAlignment="Left" x:Name="tbResult"/>
        <Button Grid.Row="1" Grid.ColumnSpan="5" Margin="0,5,0,0" Content="Calculate" x:Name="btnCalculate" Click="btnCalculate_Click" />
    </Grid>

and the code behind looks like this

public partial class MainPage : UserControl
{
    public MainPage()
    {
        InitializeComponent();
    }

    private void btnCalculate_Click(object sender, RoutedEventArgs e)
    {                       
        tbResult.Text = (Convert.ToInt32(tbFirstValue.Text)  + Convert.ToInt32(tbSecondValue.Text)).ToString();            
    }
}

It’s all about the ViewModel

The name of the ViewModel for this application will be CalculatorViewModel.

If you follow the convention of naming the ViewModel using the name of the consumer who will be using it, knowing what the ViewModel is used for is easier as the application grows.

This will also help to ensure you do not use the same ViewModel for multiple controls, something which is considered to be a best practice.

Setting the CalculatorViewModel as the data context of the Silverlight user control is usually done in one of two ways (some people implement service locators or use a provider).

setting the ViewModel as the DataContext in the code behind

public CalculatorPage()
{
    InitializeComponent();
    DataContext = new CalculatorViewModel();
}

or setting the ViewModel as the DataContext in XAML

<UserControl.DataContext>
    <local:CalculatorViewModel/>
</UserControl.DataContext>

INotifyChanged

By implementing the INotifyChanged interface (or inheriting from a base class which implements it), events can be raised when a property value changes.

For the calculator example events will be used to update the user interface when the values for the two input numbers or the calculated result change.

The code below shows how the OnPropertyChanged method is called in the property setters to raise the PropertyChangedEventHandler.

private string _firstValue;
private string _secondValue;
private string _result;

public event PropertyChangedEventHandler PropertyChanged;

public string FirstValue
{
    get { return _firstValue; }
    set
    {
        _firstValue = value;
        OnPropertyChanged("FirstValue");
    }
}

public string SecondValue
{
    get { return _secondValue; }
    set
    {
        _secondValue = value;
        OnPropertyChanged("SecondValue");
    }
}

public string Result
{
    get { return _result; }        
    private set
    {
        _result = value;
        OnPropertyChanged("Result");
    }
}
        
protected void OnPropertyChanged(string propertyName)
{
    if (PropertyChanged != null)
    {
        PropertyChanged(this,
            new PropertyChangedEventArgs(propertyName));
    }
}

The next step is to change the text controls in the XAML file to bind to the properties in the ViewModel

        <TextBox Grid.Column="0" Text="{Binding FirstValue, Mode=TwoWay}" Height="25" TextAlignment="Right"/>
        <TextBlock Grid.Column="1" Text="+" Height="25" TextAlignment="Center"/>
        <TextBox Grid.Column="2" Text="{Binding SecondValue, Mode=TwoWay}" Height="25" TextAlignment="Right"/>
        <TextBlock Grid.Column="3" Text="=" Height="25" TextAlignment="Center"/>
        <TextBlock Grid.Column="4" Text="{Binding Result, Mode=OneWay}" Height="25" TextAlignment="Left"/>

Notice how the binding mode on the text boxes are two way but the result text block is only one way.

We need to use a two way binding to be able to update the ViewModel with the values the user enters.

As the user cannot enter a value in the result text block the binding only needs to be one way.

If you want more information about data binding check out the Data Binding Overview article on MSDN.

Commands in Silverlight 4

New in Silverlight 4 are commands (WPF already had them). Commands enable us to replace the click event for the calculate button in the XAML file with a command as shown below.

<Button Grid.Row="1" Grid.ColumnSpan="5" Margin="0,5,0,0" Content="Calculate" Command="{Binding CalculateCommand}"  />

The command binds to a CalculateCommand property in the ViewModel which looks like this

private readonly ICommand _calculateCommand;
public ICommand CalculateCommand
{
    get { return _calculateCommand; }
}

So how does the command know what to do?

The answer is by using a RelayCommand (which implements the ICommand interface) and passing a method (which adds two values together) in its constructor. A relay command allows for cleaner command implementation in ViewModel classes.

The code for the RelayCommand is shown below (I can’t take any credit for this as I’ve taken it from Josh Smiths MSDN article).

public class RelayCommand : ICommand
{
    private Action _handler;
    public RelayCommand(Action handler)
    {
        _handler = handler;
    }

    private bool _isEnabled;
    public bool IsEnabled
    {
        get { return _isEnabled; }
        set
        {
            if (value != _isEnabled)
            {
                _isEnabled = value;
                if (CanExecuteChanged != null)
                {
                    CanExecuteChanged(this, EventArgs.Empty);
                }
            }
        }
    }

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

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        _handler();
    }
}

The code below shows the calculate method and how the relay command is set up in the ViewModels’ constructor

public CalculatorViewModel()
{
    _calculateCommand = new RelayCommand(Calculate){IsEnabled = true};
}

private void Calculate()
{
    Result = (Convert.ToInt32(FirstValue) + Convert.ToInt32(SecondValue)).ToString();
}

So what have we achieved?

Given that all we are doing here is adding two numbers together the effort of implementing the MVVM pattern looks to be a lot of work.

The important thing to take away is what an MVVM ViewModel looks like without the use of any third party frameworks such the MVVM Light Toolkit. The code in this post only uses the libraries that ship with Microsoft Silverlight 4.

The class diagram for the ViewModel looks like this

Silverlight MVVM ViewModel

and the complete code listing for the ViewModel is shown below

using System;
using System.ComponentModel;
using System.Windows.Input;

namespace SilverlightCalculator
{
    public class CalculatorViewModel : INotifyPropertyChanged
    {
        private string _firstValue;
        private string _secondValue;
        private string _result;

        private readonly ICommand _calculateCommand;       

        public event PropertyChangedEventHandler PropertyChanged;

        public CalculatorViewModel()
        {
            _calculateCommand = new RelayCommand(Calculate){IsEnabled = true};
        }

        private void Calculate()
        {
            Result = (Convert.ToInt32(FirstValue) + Convert.ToInt32(SecondValue)).ToString();
        }

        public string FirstValue
        {
            get { return _firstValue; }
            set
            {
                _firstValue = value;
                OnPropertyChanged("FirstValue");
            }
        }

        public string SecondValue
        {
            get { return _secondValue; }
            set
            {
                _secondValue = value;
                OnPropertyChanged("SecondValue");
            }
        }

        public string Result
        {
            get { return _result; }        
            private set
            {
                _result = value;
                OnPropertyChanged("Result");
            }
        }

        public ICommand CalculateCommand
        {
            get { return _calculateCommand; }
        }

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

With the foundation code in place adding additional properties or commands is easy.

While MVVM can be used and implemented in the wrong way (as with every pattern), by applying good software craftsmanship skills a Silverlight or WPF application using the MVVM pattern will encourage you to adopt best practices (as we will see later in the series).

If you have arrived here from a search engine, this post is part of series about refactoring Silverlight applications. So if you’re thinking calculating numbers this way is a ‘code smell’, see how this can be resolved by applying the Single Responsibility Principle to View Models in Silverlight and WPF.

Comments

  • Ro Wong

    This is post helps me a lot.

    Will you be covering how to unit test a view model in this series?

  • http://www.arrangeactassert.com Jag Reehal

    Hi Ro,

    Yes, I will be covering writing tests for ViewModels later in the series.

  • Simon Read

    This is useful to know because our company policy won’t allow us to use third party MVVM frameworks.

  • John

    This is nice stuff to read about. I’m into wpf for about 4 months now and this week i made also my first app based on mvvm!

    Thanks, i will follow you from now on.

  • Claire Taylor

    Thanks for the heads up.

    I’m just beginning to get started with Silverlight 4 hear a lot about MVVM and why I should start using it.

  • http://nothing Imran

    Please if someone tell me about the Event CanExcuteChanged in Icommand interface…i cant find it on above code

  • Karteek kumar

    This helps me a lot … regarding how to use Icommand in MVVM.

    /Karteek kumar

  • Kwon

    Thanks your great article, Jag!!
    I am studying MVVM and trying to use it in my next project. However, I have one question cannot resolve it.
    If I want to call Command property in ViewModel class, when user input some text in the TextBox control. How to call that Command property?

  • VItalij

    Very helpful, I wish I have found this information before, as I had to get it in chunks from different resources. The only thing I haven’t found is how do you add RelayCommands to UserControl. (as I have userControl instead of a button, which doesn’t have Command by default.
    I know that I have to implement ICommanSource, but I couldn’t find a lot of information on how to do it.

  • Vince

    MVVM in Silverlight made simple. Thanks that really helped me out! Needed to do MVVM in a simple prototype and found here what I failed to find elsewhere.

  • Mojam

    Thanks for this post. I saw a lot of code in net about MVVM. But not of them are helpful like you. Beginning level programmers like me who don’t know how to implement INotificationPropertyChange etc. how thy will be able to implement them? Please can you explain about Unit test and finally create a Business Application with Silverlight4, Wcf Ria with MVVM Pattern with step by step instruction. That would be helpful for me like beginning level silverlight4 users.
    Thanks for Previous Post.
    Thanks in Advance for next Post

  • Jm

    Good job Jag!
    glad to see Silverlight catching up with WPF.
    This is some powerful stuff.

  • Qmikej

    Need an example with Validation for a collection of objects using MVVM. I cant find one anywhere so this would be a great example if it was added.

  • Anonymous

    Yep that would an interesting post, I’ll add it to my list of things to do.

  • Mohd Ik85

    This helps me a lot … regarding how to use Icommand in MVVM.

  • Kiruba Sankars

    It’s Very Good…………

  • Jsn Net

    Woooww…nice..I enjoyed.. and solved my probl too.

  • Idontwanttogiveoutmyemail

    Great article, thanks!

  • Anay9213

    Very nice……

  • PK

    Nice and simple explanation with no too much additional code to bloat the solution. Well done..

  • http://www.facebook.com/douglas.prandini Douglas S. Prandini

    it is the best article i have read on internet about RelayCommand, Thank you for share it

  • Dallas

    Thank you so much.
    It is really nice and easy to understand article. It helps me understand how to implement commands in my app.

  • Shohel

    Nice 

  • Levan Arabuli

    great article!

  • Levan Arabuli

    great article!

  • Pradeep

     Thanks a lot for this article :)

  • Namrata

    You made understanding commands in MVVM easier, thanks :)

  • Pingback: Những ví dụ Cụ thể về WPF Command Model « Tô Mỳ Minh Duy (CTTMMD)