Posted by: Zeeshan Amjad | January 21, 2010

Introduction to MVVM


We already saw the example of command binding here and here. In fact that was the first step towards the MVVM (Model, View, ViewModel). In that program we introduced the property of ICommand interface and implement that in our command class.

Now let’s decouple these concept more. This time we are going to move the ICommand interface type property from our class class. Our data class purely contains only data nothing else. This is also known as Model of our program.

If we move ICommand from the data then there should be a place where we are suppose to make ICommand based properties and implement them. Just for reusability we make a separate class to implement ICommand interface and uses the object of that class wherever we need to implement it. We can say our MyCommand class is like a utility class.

Now comes to the middle layer also known as ViewModel. This class is suppose to expose all the functionality using ICommand based interface. Here we are using our utility class MyCommand to implement ICommand interface.

Here is a block diagram to explain it better. 

MVVM

Now let’s take a look at these block one by one. Our Model block is doesn’t know anything about ViewModel or View. It just contains data. Here is our simple implementation of Numbers class.

  1: public class Numbers : INotifyPropertyChanged
  2: {
  3:     private int _firstNo;
  4:     private int _secondNo;
  5:     private int _result;
  6:     private String _resultLabel;
  7: 
  8:     public int FirstNo
  9:     { 
 10:         get
 11:         {
 12:             return _firstNo;
 13:         }
 14:         set
 15:         {
 16:             _firstNo = value;
 17:             RaisePropertyChanged("FirstNo");
 18:         }
 19:     }
 20: 
 21:     public int SecondNo
 22:     { 
 23:         get
 24:         {
 25:             return _secondNo;
 26:         }
 27:         set
 28:         {
 29:             _secondNo = value;
 30:             RaisePropertyChanged("SecondNo");
 31:         }
 32:     }
 33: 
 34:     public String ResultLabel
 35:     { 
 36:         get
 37:         {
 38:             return _resultLabel;
 39:         }
 40:         set
 41:         {
 42:             _resultLabel = value;
 43:             RaisePropertyChanged("ResultLabel");
 44:         }
 45:     }
 46: 
 47:     public int Result
 48:     { 
 49:         get
 50:         {
 51:             return _result;
 52:         }
 53:         set
 54:         {
 55:             _result = value;
 56:             RaisePropertyChanged("Result");
 57:         }
 58:     }
 59: 
 60:     public event PropertyChangedEventHandler PropertyChanged;
 61: 
 62:     private void RaisePropertyChanged(string propertyName)
 63:     {
 64:         PropertyChangedEventHandler handler = this.PropertyChanged;
 65: 
 66:         if (handler != null)
 67:         {
 68:             handler(this, new PropertyChangedEventArgs(propertyName));
 69:         }
 70:     }
 71: }

Here we implement the INotifyPropertyChanged property change interface. To implement two way binding we need to either implement this interface or make data as a DependencyProperty rather than normal CLR properties. Here we use INotifyPropertyChanged interface. Now let’s take a look at our utility class to implement ICommand interface. Here is a code of our utility class.

  1: public class MyCommand : ICommand
  2: {
  3:     public Func<int> Function
  4:     { get; set; }
  5: 
  6:     public MyCommand()
  7:     {
  8:     }
  9: 
 10:     public MyCommand(Func<int> function)
 11:     {
 12:         Function = function;
 13:     }
 14: 
 15:     public bool CanExecute(object parameter)
 16:     {
 17:         if (Function != null)
 18:         {
 19:             return true;
 20:         }
 21: 
 22:         return false;
 23:     }
 24: 
 25: 
 26:     public void Execute(object parameter)
 27:     {
 28:         if (Function != null)
 29:         {
 30:             Function();
 31:         }
 32:     }
 33: 
 34:     public event EventHandler CanExecuteChanged
 35:     {
 36:         add { CommandManager.RequerySuggested += value; }
 37:         remove { CommandManager.RequerySuggested -= value; }
 38:     }
 39: }
 40: 

This implementation accept one function that doesn’t take any parameter but return integer. To be very honest we actually even don’t need to return integer, because we are not using it anywhere. Now lets take a look at ViewModel class. This class exposed two properties of ICommand type and their implementation is provided by our MyCommand Utility class. In addition we also implement INotifyPropertyChanged interface to support two way binding. Here is an implementation of ViewModel class.

  1: public class MyViewModel : INotifyPropertyChanged
  2: {
  3:     private Numbers _numbers;
  4:     public event PropertyChangedEventHandler PropertyChanged;
  5: 
  6:     public MyViewModel()
  7:     {
  8:         _numbers = new Numbers();
  9:         CalculateGCDCommand = new MyCommand(CalculateGCD);
 10:         CalculateLCMCommand = new MyCommand(CalculateLCM);
 11:     }
 12: 
 13:     public Numbers Numbers
 14:     {
 15:         get
 16:         {
 17:             return _numbers;
 18:         }
 19:         set
 20:         {
 21:             _numbers = value;
 22:             RaisePropertyChanged("Numbers");
 23:         }
 24:     }
 25: 
 26:     private void RaisePropertyChanged(string propertyName)
 27:     {
 28:         PropertyChangedEventHandler handler = this.PropertyChanged;
 29: 
 30:         if (handler != null)
 31:         {
 32:             handler(this, new PropertyChangedEventArgs(propertyName));
 33:         }
 34:     }
 35: 
 36:     public ICommand CalculateGCDCommand
 37:     { get; set; }
 38: 
 39:     public ICommand CalculateLCMCommand
 40:     { get; set; }
 41: 
 42:     private int CalculateGCD()
 43:     {
 44:         int x = Numbers.FirstNo;
 45:         int y = Numbers.SecondNo;
 46: 
 47:         Numbers.Result = CalculateGCDInternal(x, y);
 48:         Numbers.ResultLabel = "GCD";
 49: 
 50:         return Numbers.Result;
 51:     }
 52: 
 53:     private int CalculateGCDInternal(int x, int y)
 54:     {
 55:         if (x == 0)
 56:             return 0;
 57: 
 58:         while (y != 0)
 59:         {
 60:             if (x > y)
 61:                 x = x - y;
 62:             else
 63:                 y = y - x;
 64:         }
 65: 
 66:         return x;
 67:     }
 68: 
 69:     private int CalculateLCM()
 70:     {
 71:         int x = Numbers.FirstNo;
 72:         int y = Numbers.SecondNo;
 73: 
 74:         int lcm = x * y / CalculateGCDInternal(x, y);
 75: 
 76:         Numbers.Result = lcm;
 77:         Numbers.ResultLabel = "LCM";
 78:         return lcm;
 79:     }
 80: }
 81: 

Here in the constructor, we bind our functions with ICommand type properties. Our window class is very simple and we just set the data context in window class to our view model class. We define our view in XAML and do all the communication with data and command binding. Here is complete XAML file of our program.

  1: <Window x:Class="WpfCommandBinding.Window1"
  2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  4:     xmlns:local="clr-namespace:WpfCommandBinding"
  5:     Title="MVVM" Height="200" Width="300">
  6:     <Grid Name="grid" Background="Wheat">
  7:         <Grid.ColumnDefinitions>
  8:             <ColumnDefinition/>
  9:             <ColumnDefinition/>
 10:         </Grid.ColumnDefinitions>
 11:         <Grid.RowDefinitions>
 12:             <RowDefinition/>
 13:             <RowDefinition/>
 14:             <RowDefinition/>
 15:             <RowDefinition/>
 16:         </Grid.RowDefinitions>
 17:         <TextBlock Grid.Column="0" Grid.Row="0" Margin="5"
 18:                    VerticalAlignment="Center" Text="Enter first number"/>
 19:         <TextBox Grid.Column="1" Grid.Row="0" Margin="5" 
 20:                  VerticalAlignment="Center" Text="{Binding Path=Numbers.FirstNo}"/>
 21:         <TextBlock Grid.Column="0" Grid.Row="1" Margin="5"
 22:                    VerticalAlignment="Center" Text="Enter second number"/>
 23:         <TextBox Grid.Column="1" Grid.Row="1" Margin="5" 
 24:                    VerticalAlignment="Center" Text="{Binding Path=Numbers.SecondNo}"/>
 25:         <TextBlock Grid.Column="0" Grid.Row="2" Margin="5"
 26:                    VerticalAlignment="Center" Text="{Binding Path=Numbers.ResultLabel}"/>
 27:         <TextBlock Grid.Column="1" Grid.Row="2" Margin="5"
 28:                    VerticalAlignment="Center" Text="{Binding Path=Numbers.Result}"/>
 29:         <Button Grid.Column="0" Grid.Row="3" Margin="5" 
 30:                 Content="GCD" Command="{Binding CalculateGCDCommand}"/>
 31:         <Button Grid.Column="1" Grid.Row="3" Margin="5" 
 32:                 Content="LCM" Command="{Binding CalculateLCMCommand}"/>        
 33:     </Grid>
 34: </Window>
 35: 

And here is complete C# code of the program.

  1: using System;
  2: using System.Collections.Generic;
  3: using System.Linq;
  4: using System.Text;
  5: using System.Windows;
  6: using System.Windows.Controls;
  7: using System.Windows.Data;
  8: using System.Windows.Documents;
  9: using System.Windows.Input;
 10: using System.Windows.Media;
 11: using System.Windows.Media.Imaging;
 12: using System.Windows.Navigation;
 13: using System.Windows.Shapes;
 14: using System.ComponentModel;
 15: 
 16: namespace WpfCommandBinding
 17: {
 18:     /// <summary>
 19:     /// Interaction logic for Window1.xaml
 20:     /// </summary>
 21:     public partial class Window1 : Window
 22:     {
 23:         private Numbers nos = new Numbers();
 24: 
 25:         public Window1()
 26:         {
 27:             InitializeComponent();
 28: 
 29:             DataContext = new MyViewModel();
 30:         }
 31:     }
 32: 
 33:     public class MyViewModel : INotifyPropertyChanged
 34:     {
 35:         private Numbers _numbers;
 36:         public event PropertyChangedEventHandler PropertyChanged;
 37: 
 38:         public MyViewModel()
 39:         {
 40:             _numbers = new Numbers();
 41:             CalculateGCDCommand = new MyCommand(CalculateGCD);
 42:             CalculateLCMCommand = new MyCommand(CalculateLCM);
 43:         }
 44: 
 45:         public Numbers Numbers
 46:         {
 47:             get
 48:             {
 49:                 return _numbers;
 50:             }
 51:             set
 52:             {
 53:                 _numbers = value;
 54:                 RaisePropertyChanged("Numbers");
 55:             }
 56:         }
 57: 
 58:         private void RaisePropertyChanged(string propertyName)
 59:         {
 60:             PropertyChangedEventHandler handler = this.PropertyChanged;
 61: 
 62:             if (handler != null)
 63:             {
 64:                 handler(this, new PropertyChangedEventArgs(propertyName));
 65:             }
 66:         }
 67: 
 68:         public ICommand CalculateGCDCommand
 69:         { get; set; }
 70: 
 71:         public ICommand CalculateLCMCommand
 72:         { get; set; }
 73: 
 74:         private int CalculateGCD()
 75:         {
 76:             int x = Numbers.FirstNo;
 77:             int y = Numbers.SecondNo;
 78: 
 79:             Numbers.Result = CalculateGCDInternal(x, y);
 80:             Numbers.ResultLabel = "GCD";
 81: 
 82:             return Numbers.Result;
 83:         }
 84: 
 85:         private int CalculateGCDInternal(int x, int y)
 86:         {
 87:             if (x == 0)
 88:                 return 0;
 89: 
 90:             while (y != 0)
 91:             {
 92:                 if (x > y)
 93:                     x = x - y;
 94:                 else
 95:                     y = y - x;
 96:             }
 97: 
 98:             return x;
 99:         }
100: 
101:         private int CalculateLCM()
102:         {
103:             int x = Numbers.FirstNo;
104:             int y = Numbers.SecondNo;
105: 
106:             int lcm = x * y / CalculateGCDInternal(x, y);
107: 
108:             Numbers.Result = lcm;
109:             Numbers.ResultLabel = "LCM";
110:             return lcm;
111:         }
112:     }
113: 
114:     public class MyCommand : ICommand
115:     {
116:         public Func<int> Function
117:         { get; set; }
118: 
119:         public MyCommand()
120:         {
121:         }
122: 
123:         public MyCommand(Func<int> function)
124:         {
125:             Function = function;
126:         }
127: 
128:         public bool CanExecute(object parameter)
129:         {
130:             if (Function != null)
131:             {
132:                 return true;
133:             }
134: 
135:             return false;
136:         }
137: 
138: 
139:         public void Execute(object parameter)
140:         {
141:             if (Function != null)
142:             {
143:                 Function();
144:             }
145:         }
146: 
147:         public event EventHandler CanExecuteChanged
148:         {
149:             add { CommandManager.RequerySuggested += value; }
150:             remove { CommandManager.RequerySuggested -= value; }
151:         }
152:     }
153: 
154:     public class Numbers : INotifyPropertyChanged
155:     {
156:         private int _firstNo;
157:         private int _secondNo;
158:         private int _result;
159:         private String _resultLabel;
160: 
161:         public int FirstNo
162:         { 
163:             get
164:             {
165:                 return _firstNo;
166:             }
167:             set
168:             {
169:                 _firstNo = value;
170:                 RaisePropertyChanged("FirstNo");
171:             }
172:         }
173: 
174:         public int SecondNo
175:         { 
176:             get
177:             {
178:                 return _secondNo;
179:             }
180:             set
181:             {
182:                 _secondNo = value;
183:                 RaisePropertyChanged("SecondNo");
184:             }
185:         }
186: 
187:         public String ResultLabel
188:         { 
189:             get
190:             {
191:                 return _resultLabel;
192:             }
193:             set
194:             {
195:                 _resultLabel = value;
196:                 RaisePropertyChanged("ResultLabel");
197:             }
198:         }
199: 
200:         public int Result
201:         { 
202:             get
203:             {
204:                 return _result;
205:             }
206:             set
207:             {
208:                 _result = value;
209:                 RaisePropertyChanged("Result");
210:             }
211:         }
212: 
213:         public event PropertyChangedEventHandler PropertyChanged;
214: 
215:         private void RaisePropertyChanged(string propertyName)
216:         {
217:             PropertyChangedEventHandler handler = this.PropertyChanged;
218: 
219:             if (handler != null)
220:             {
221:                 handler(this, new PropertyChangedEventArgs(propertyName));
222:             }
223:         }
224:     }
225: }
226: 

This would be the output of the program when we input two numbers and click the GCD button.

MVVM_Output_01

And this would be the output when we click on LCM button.

MVVM_Output_02

Advertisements

Responses

  1. […] Patterns using Dependency Property We have already seen the example of using MVVM using INotifyPropertyChange interface. But we can do the same thing with dependency […]

  2. I liked the article. Simple, yet illustrates MVVM concepts.

    • Thanks to like it.

  3. Hi,
    You have a fantastic site with lots of good examples.

    It would be very helpful if you could provide a download section.
    Or please remove those line numbers from your code blocks as when copying and pasting we have to remove them.

    Again fantastic tutorials.

    • Thanks to like it. I am currently working on exploring different options to give the download section. Currently i am busy in some other stuff, as soon as i am done, i will make that section available.

      For line numbers, i am using one plug in for Windows Live for color coding. I will again revisited that plug in and see if i can do something better.

      Again thanks a lot to like my site.

      Regards
      Zeeshan Amjad

  4. Great Article, thanks for easy explaination.

    Is following neccesary?

    Line 23: private Numbers nos = new Numbers();
    in “partial class Window1 : Window”

    because once you have set DataContext to ViewModel instance, it will have its own Numbers instance binded to Controls.

    • Thanks to like it and point out my mistake. Yes line 23 is unnecessary, it is in fact part of ViewModel. It looks like that i started from existing project and forget to remove all the code.

      Regards
      Zeeshan Amjad

  5. Very Nice. I have been trying to run this in winRT and found that I had to replace public event EventHandler CanExecuteChanged

    {

    add { CommandManager.RequerySuggested += value; }

    remove { CommandManager.RequerySuggested -= value; }

    }
    with
    public event EventHandler CanExecuteChanged;
    public void RaiseCanExecuteChanged()
    {
    if (CanExecuteChanged != null)
    CanExecuteChanged(this, EventArgs.Empty);
    }

    and also I had to mention mode=TwoWay for FirstNo and SecondNo to calculate the numbers properly.

    One of your great articles as always.

    • Hi Ajay

      Thanks for pointing this out. I will keep this in mind when working on WinRT project.

      Regards
      Zeeshan Amjad


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

Categories

%d bloggers like this: