Posted by: Zeeshan Amjad | January 13, 2010

Command Binding


WPF have very powerful concept command binding. We can not only bind the data but also the commands in WPF. And with command binding and data binding we can implement very powerful and reusable design commonly known as MVVM (Model View ViewModel). Before going to discuss the MVVM lets complete our ground work and study the command binding.

The basic concept of command binding is to implement ICommand interface. There are two methods and one events in this interface and we have to implements all of them to create its class. Here is our implementation of our ICommand interface that takes one method without any parameter but return boolean.

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

We create one more class to store the information. We also implement the INotifyPropertyChanged interface so whenever there is any change in the interface then the properties update accordingly. Here is our class of number.

  1: public class Numbers : INotifyPropertyChanged
  2: {
  3:     private int _firstNo;
  4:     private int _secondNo;
  5: 
  6:     public int FirstNo
  7:     {
  8:         get
  9:         {
 10:             return _firstNo;
 11:         }
 12: 
 13:         set
 14:         {
 15:             _firstNo = value;
 16:             OnPropertyChanged("FirstNo");
 17:         }
 18:     }
 19: 
 20:     public int SecondNo
 21:     {
 22:         get
 23:         {
 24:             return _secondNo;
 25:         }
 26: 
 27:         set
 28:         {
 29:             _secondNo = value;
 30:             OnPropertyChanged("SecondNo");
 31:         }
 32:     }
 33: 
 34:     public ICommand CalculateGCD
 35:     { get; set; }
 36: 
 37:     public ICommand CalculateLCM
 38:     { get; set; }
 39: 
 40:     public event PropertyChangedEventHandler PropertyChanged;
 41: 
 42:     private void OnPropertyChanged(string propertyName)
 43:     {
 44:         if (this.PropertyChanged != null)
 45:         {
 46:             this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
 47:         }
 48:     }
 49: }
 50: 

We create two objects of our command objects and set the methods with our handler. Here is a piece of code to do this.

  1: MyCommand command1 = new MyCommand();
  2: command1.Function = CalculateGCD;
  3: nos.CalculateGCD = command1;
  4: 
  5: MyCommand command2 = new MyCommand();
  6: command2.Function = CalculateLCM;
  7: nos.CalculateLCM = command2;
  8: 

Now we can do a binding with command. Here is a piece of XAML code to do command binding.

  1: <Button Grid.Column="0" Grid.Row="2" Margin="5" 
  2: 	Content="GCD" Command="{Binding CalculateGCD}"/>
  3: <Button Grid.Column="1" Grid.Row="2" Margin="5" 
  4: 	Content="LCD" Command="{Binding CalculateLCM}"/>

Now if we click the first button then it will execute the CalculateGCD method and if we click on the second button it will execute the CalculateLCM method. Here is complete XAML code of the 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:     Title="Command Binding" Height="200" Width="300">
  5:     <Grid Name="grid" Background="Wheat">
  6:         <Grid.ColumnDefinitions>
  7:             <ColumnDefinition/>
  8:             <ColumnDefinition/>
  9:         </Grid.ColumnDefinitions>
 10:         <Grid.RowDefinitions>
 11:             <RowDefinition/>
 12:             <RowDefinition/>
 13:             <RowDefinition/>
 14:         </Grid.RowDefinitions>
 15:         <TextBlock Grid.Column="0" Grid.Row="0" Margin="5"
 16:                    VerticalAlignment="Center" Text="Enter first number"/>
 17:         <TextBox Grid.Column="1" Grid.Row="0" Margin="5" Name="txtFirstNo"
 18:                  VerticalAlignment="Center" Text="{Binding Path=FirstNo}"/>
 19:         <TextBlock Grid.Column="0" Grid.Row="1" Margin="5"
 20:                    VerticalAlignment="Center" Text="Enter second number"/>
 21:         <TextBox Grid.Column="1" Grid.Row="1" Margin="5" Name="txtSecondNo"
 22:                    VerticalAlignment="Center" Text="{Binding Path=SecondNo}"/>
 23:         <Button Grid.Column="0" Grid.Row="2" Margin="5" 
 24:                 Content="GCD" Command="{Binding CalculateGCD}"/>
 25:         <Button Grid.Column="1" Grid.Row="2" Margin="5" 
 26:                 Content="LCM" Command="{Binding CalculateLCM}"/>
 27:     </Grid>
 28: </Window>
 29: 

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:             MyCommand command1 = new MyCommand();
 29:             command1.Function = CalculateGCD;
 30:             nos.CalculateGCD = command1;
 31: 
 32:             MyCommand command2 = new MyCommand();
 33:             command2.Function = CalculateLCM;
 34:             nos.CalculateLCM = command2;
 35: 
 36:             grid.DataContext = nos;
 37:         }
 38: 
 39:         private int CalculateGCDInternal(int x, int y)
 40:         {
 41:             if (x == 0)
 42:                 return 0;
 43: 
 44:             while (y != 0)
 45:             {
 46:                 if (x > y)
 47:                     x = x - y;
 48:                 else
 49:                     y = y - x;
 50:             }
 51: 
 52:             return x;
 53:         }
 54: 
 55:         private int CalculateGCD()
 56:         {
 57:             int x = nos.FirstNo;
 58:             int y = nos.SecondNo;
 59: 
 60:             int gcd = CalculateGCDInternal(x, y);
 61:             MessageBox.Show(gcd.ToString(), "GCD");
 62:             return gcd;
 63:         }
 64: 
 65:         private int CalculateLCM()
 66:         {
 67:             int x = nos.FirstNo;
 68:             int y = nos.SecondNo;
 69:             int lcm = x * y / CalculateGCDInternal(x, y);
 70:             MessageBox.Show(lcm.ToString(), "LCM");
 71:             return x * y / lcm;
 72:         }
 73:     }
 74: 
 75:     public class MyCommand : ICommand
 76:     {
 77:         public Func<int> Function
 78:         { get; set; }
 79: 
 80:         public bool CanExecute(object parameter)
 81:         {
 82:             if (Function != null)
 83:             {
 84:                 return true;
 85:             }
 86: 
 87:             return false;
 88:         }
 89: 
 90:         public void Execute(object parameter)
 91:         {
 92:             if (Function != null)
 93:             {
 94:                 Function();
 95:             }
 96:         }
 97: 
 98:         public event EventHandler CanExecuteChanged
 99:         {
100:             add { CommandManager.RequerySuggested += value; }
101:             remove { CommandManager.RequerySuggested -= value; }
102:         }
103:     }
104: 
105:     public class Numbers : INotifyPropertyChanged
106:     {
107:         private int _firstNo;
108:         private int _secondNo;
109: 
110:         public int FirstNo
111:         {
112:             get
113:             {
114:                 return _firstNo;
115:             }
116: 
117:             set
118:             {
119:                 _firstNo = value;
120:                 OnPropertyChanged("FirstNo");
121:             }
122:         }
123: 
124:         public int SecondNo
125:         {
126:             get
127:             {
128:                 return _secondNo;
129:             }
130: 
131:             set
132:             {
133:                 _secondNo = value;
134:                 OnPropertyChanged("SecondNo");
135:             }
136:         }
137: 
138:         public ICommand CalculateGCD
139:         { get; set; }
140: 
141:         public ICommand CalculateLCM
142:         { get; set; }
143: 
144:         public event PropertyChangedEventHandler PropertyChanged;
145: 
146:         private void OnPropertyChanged(string propertyName)
147:         {
148:             if (this.PropertyChanged != null)
149:             {
150:                 this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
151:             }
152:         }
153:     }
154: }
155: 

 

Here is the output of the program.

CommandBinding

Advertisements

Responses

  1. […] 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 […]

  2. […] Binding with Parameter Passing We saw the example of command binding to calculate the GCD and LCM of two input numbers. Now lets extend this idea and trying to pass […]

  3. […] Routed Commands We have already seen example of implementing ICommand interface here and here. WPF already define one class which already implement ICommand interface. That class is […]

  4. Very very helpful. But please appropriate formate the code. Use code snippet. It will increase readability. I’m waiting….

    • Thanks to like it. I was using Windows Live Writer with one code formatting plug in to write the code. I will take a look at this and will update the code formatting if i will come across any otehr good code formatting plug in.

      Regards
      Zeeshan Amjad

      • Hello Zeeshan.
        Thanking for sharing your Knowledge which really helps us a lot .
        i have tried the above Article and had a problem to compile the code,which was providing me an error for the line No:23
        private Numbers nos = new Numbers();
        Error:The type or namespace name ‘Numbers’ could not be found (are you missing a using directive or an assembly reference
        am i missing any namespace to be added for the above line of code.
        Could you please help me with this. If you can help me please email me.
        Thank you in advance.

      • Thanks to like it.

        I created a Number class in the same file. Make sure you have that class. If you created that class in another namespace, please include the referenfce of that namespace.

        Regards
        Zeeshan Amjad

  5. Could you please upload the project (in .zip or .rar format)?
    Excellent blog!

    • Thanks to like my blog. I couldn’t find a way to upload project file at wordpress. I am thinking to upload the project at skydrive and post a link here.

      Thanks to like my blog and visit here.

      Regards
      Zeeshan Amjad

  6. hey there can u pls tell me where to start. seriously i have to backtrack your dates of upload, to get how to start to learn wpf. and thanks for such good blog.


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: