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.

How To Refactor And Build Better Microsoft Silverlight Applications

As with all development technologies if you asked two developers how to solve a problem it’s unlikely both would come up with the same solution.

It’s no surprise then the same solution to a problem using Silverlight and WPF applications can be implemented in a number of ways.

In a series of posts I want to show how we can refactor a Silverlight application which “works” to be a lot cleaner, easier to maintain and adheres to good development practices.

Although I’m using Silverlight many of the changes and suggestions would also apply to a WPF application.

So what’s the application?

The application adds two numbers together.

Silverlight Calculator

Yes that’s it. Click here to see a live demo of the calclator.

Using a simple example (as opposed to a huge complex monster) allows us to focus on refactoring and making improvements rather than trying to understand what the application is doing and wading through hundreds of lines of code.

So what’s wrong with it?

The XAML is shown below

    <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 this is what the code behind looks like

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();
    }
}

As it stands the application:

  • Contains code in the code behind file. OK it’s not so much of an issue for this example and is down to individual preference, but this can quickly become a nightmare to maintain during the life of an application
  • Isn’t unit testable – we can’t test two values can be added together
  • Has no separation of concerns – the code behind shouldn’t be responsible for adding the numbers together
  • A lot of repetition for the styling of the input boxes – if we wanted to make the input boxes bigger we would have to make multiple changes, ideally changes should only need to be made in one place.
  • No validation – if the user enters alphabetical characters into application and hits the calculate button the application crashes

So how are we going to improve it?

By taking an agile approach the aim at the end of each refactoring is to have a releasable application i.e. be able to add two numbers together. Therefore each refactoring will involve small incremental changes.

After each refactoring exercise we will review the application to see what improvements have been made and if any new problems have been introduced…

WPF and Silverlight Value Converter Example in VB and C#

In this post I want to show how a value converter in Silverlight and WPF can be used to output the value of a slider control.

The code used in this post downloaded here.

Why Are Value Converters Useful?

In the screen shot below you can see a slider control and two numbers representing its value. As you can see the value not using a converter is somewhat lacking in its visual appeal and isn’t user friendly.

Silverlight Value Converter Example

The XAML used to create this is shown below

<UserControl x:Class="ValueConverterExample.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:ValueConverterExample" mc:Ignorable="d"
    d:DesignHeight="300" d:DesignWidth="500">
    <UserControl.Resources>
        <local:SliderValueConvertor x:Key="SliderValueConvertor"/>
    </UserControl.Resources>

    <Grid x:Name="LayoutRoot" Background="White" Height="Auto" Width="500" Margin="0,50,0,0">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="4*"/>
            <ColumnDefinition Width="3*"/>
            <ColumnDefinition Width="3*"/>
        </Grid.ColumnDefinitions>

        <TextBlock Grid.Column="1" Text="Without a Convertor" Margin="5" HorizontalAlignment="Center"/>
        <TextBlock Grid.Column="2" Text="With a Convertor" Margin="5" HorizontalAlignment="Center"/>
        <Slider x:Name="mySilder" Grid.Row="1" Minimum="0" Maximum="10" Margin="5" SmallChange="1" />
        <TextBlock x:Name="txtBlkWithoutConverter" Grid.Row="1" Grid.Column="1" Text="{Binding ElementName=mySilder, Path=Value}" VerticalAlignment="Center"  HorizontalAlignment="Center"/>
        <TextBlock  x:Name="txtBlkUsingConverter" Grid.Row="1" Grid.Column="2" Text="{Binding ElementName=mySilder, Path=Value, Converter={StaticResource SliderValueConvertor}}" VerticalAlignment="Center"  HorizontalAlignment="Center"/>
    </Grid>
</UserControl>

Note how in the text binding for the txtBlkUsingConverter text block a SliderValueConvertor is used.

The code for the value converter looks like this in VB

Public Class SliderValueConvertor
	Implements IValueConverter
	Public Function Convert(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object
		Return Math.Round(CDbl(value))
	End Function

	Public Function ConvertBack(value As Object, targetType As Type, parameter As Object, culture As CultureInfo) As Object
		Return Nothing
	End Function
End Class

and like this in C#

public class SliderValueConvertor : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return Math.Round((double) value);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return null;
    }
}

By implementing the IValueConverter interface the slider value can be rounded to show a whole number. There’s no need to support the ConvertBack method because the text block isn’t editable.

I could have done this using code behind…

Yes if you created a handler for the slider value changed event in the code behind it’s possible to achieve the same result. But I find this solution much cleaner and can be used if you’re implementing the MVVM pattern.

Page 2 of 212