In this article, we will learn about ICommand interface and its use in generic implementation of Command while working with MVVM Pattern in WPF/Silverlight applications.
Introduction
In this article, we will learn about ICommand
interface and its use in generic implementation of Command
while working with MVVM (Model View ViewModel) Pattern in WPF/Silverlight applications. First, we will understand about Command
and then look into members of ICommand
interface. We will create a demo application in WPF to learn the use of ICommand
. In the demo application, we will use MVVM Pattern also.
Note: For this article, as a prerequisite, we must have basic understanding of WPF and MVVM pattern. If you are new to MVVM Pattern, please have a look at Wiki and MSDN Page.
Outline
What is Command
In WPF context, Command
is any class which implement ICommand
interface. There is minute difference between Commands and Events. Events are defined and associated with UI Controls. But Commands are more abstract and focused on what to be done. One Command can be associated with multiple UI Controls/Options. For example, a Save Command we can be executed on Save Button Click, or by pressing Ctrl+S or by choosing Save option from Menu bar. To have interactions in application, we use either events or commands.
In WPF applications, we have two options to provide interactions in UI:
- The first option is using events and write code in code-behind file which we want to execute on a particular event, if we are not following MVVM pattern. There are many inbuilt
RoutedEvent
s available in WPF to use for this case. - The second option is write code block which we want to execute in
ViewModel
and invoke that code using Command, if we are following MVVM pattern. If we are using MVVM Pattern, then generally we should not write code in code-behind files. So we cannot use RoutedEvents because RoutedEvents are not accessible in ViewModels. That is why we have to use Commands to execute desired code block written in ViewModel. Thus Commands provide glue between View and ViewModel for interactivity.
ICommand Interface
ICommand
is an interface which has three members as shown in the below table:
Member Of ICommand | Description |
bool CanExecute(object parameter) | CanExecute method takes an object as an argument and returns bool . If it returns true , associated command can be executed. If it returns false, associated command cannot be executed. Often, we pass a delegate to this method as an object which returns a bool . For that, we can use inbuilt delegate like Action , Predicate or Func .
|
event EventHandler CanExecuteChanged | This is used to notify the UI controls associated with Command if Command can be executed. Based on notification of this event, UI controls change its status as enabled or disabled. Basically, while "CanExecute " method executes and if there is a change in method's output (true /false ), then this event is fired.
|
void Execute(object parameter) | This is the method which does actual work which is intended for the Command . This method executes only if CanExecute method returns true . It takes an object as an argument and we generally pass a delegate into this method. The delegate holds a method reference which is supposed to execute when Command is fired.
|
Why ICommand Interface
ICommand
is core interface in WPF for Command
s. It is heavily used in MVVM and Prism based application. But use of ICommand
interface is not just limited to MVVM. There are many inbulit Command
s which already implements this interface provided by WPF/Silverlight/Prism framework. The base class RoutedCommand
implements ICommand
interface. And WPF provides MediaCommands
, ApplicationCommands
, NavigationCommands
, ComponentCommands
, and EditingCommands
which uses RoutedCommand
class. For more information, please have a look at the MSDN Page.
To make it easy to understand, let us create a demo application.
Overview of Demo Application
The demo application is doing very basic calculation, just to show ICommand
interface implementation. Demo application is having two textbox
es to accept input value, one label to show output and four buttons to perform calculations. Four buttons are used to perform add, subtraction, multiply and divide operation. After entering values in textbox
es, then on a button click, the associated command will get fired and it shows result in the label. How we will achieve the above functionality, we will see in further steps. Please download the code sample attached as it will be helpful to understand and follow up explanations given further.
The final screenshot of the demo application is as shown below:
Creating UI for Demo App
Now fire up Visual Studio and to create demo application, please follow the steps given below:
Step 1
Create a WPF application named as SimpleCommandDemoApp
. Make project structure by adding folders and files same as shown below. In further steps, we will write code in those files.
Step 2
First, we will create a layout demo UI. To do that, we will create the grid with four rows and four columns. Controls will be placed in this grid by specifying rows and columns position. Write the same code as shown below in CalculatorView.xaml file.
<Grid DataContext="{Binding Source={StaticResource calculatorVM}}"
Background="#FFCCCC">
<Grid.RowDefinitions>
<RowDefinition Height="80"></RowDefinition>
<RowDefinition></RowDefinition>
<RowDefinition Height="80"></RowDefinition>
<RowDefinition Height="44"></RowDefinition>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
<ColumnDefinition></ColumnDefinition>
</Grid.ColumnDefinitions>
<Label Grid.Row="0" Grid.Column="0"
Grid.ColumnSpan="4" FontSize="25" VerticalAlignment="Top"
HorizontalAlignment="Center" Foreground="Blue" Content="ICommand Demo"/>
<Label Grid.Row="0" Grid.Column="0"
Grid.ColumnSpan="2" Margin="10,0,0,0" VerticalAlignment="Bottom"
FontSize="20" Content="First Input"/>
<Label Grid.Row="0" Grid.Column="2" Grid.ColumnSpan="2"
Margin="10,0,0,0" VerticalAlignment="Bottom"
FontSize="20" Content="Second Input"/>
<TextBox Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2"
Margin="10,0,0,0" FontSize="20" HorizontalAlignment="Left"
Height="30" Width="150"
TextAlignment="Center" Text="{Binding FirstValue, Mode=TwoWay}"/>
<TextBox Grid.Row="1" Grid.Column="2" Grid.ColumnSpan="2"
Margin="10,0,0,0" FontSize="20" HorizontalAlignment="Left"
Height="30" Width="150" TextAlignment="Center"
Text="{Binding SecondValue, Mode=TwoWay}"/>
<Rectangle Grid.Row="2" Grid.Column="0"
Grid.ColumnSpan="4" Fill="LightBlue"></Rectangle>
<Button Grid.Row="2" Grid.Column="0" Content="+"
Margin="10,0,0,0" HorizontalAlignment="Left" Height="50"
Width="50" FontSize="30" Command="{Binding AddCommand}"></Button>
<Button Grid.Row="2" Grid.Column="1" Content="-"
Margin="10,0,0,0" HorizontalAlignment="Left" Height="50"
Width="50" FontSize="30" Command="{Binding SubstractCommand}"></Button>
<Button Grid.Row="2" Grid.Column="2" Content="*"
Margin="10,0,0,0" HorizontalAlignment="Left" Height="50"
Width="50" FontSize="30" Command="{Binding MultiplyCommand}"></Button>
<Button Grid.Row="2" Grid.Column="3" Content="%"
Margin="10,0,0,0" HorizontalAlignment="Left" Height="50"
Width="50" FontSize="30" Command="{Binding DivideCommand}"></Button>
<Label Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2"
FontSize="25" Margin="10,0,0,0" HorizontalAlignment="Left"
Height="50" Content="Result : "/>
<TextBlock Grid.Row="3" Grid.Column="2" Grid.ColumnSpan="2"
FontSize="20" Margin="10,0,0,0" Background="BlanchedAlmond"
TextAlignment="Center" HorizontalAlignment="Left" Height="36"
Width="150" Text="{Binding Output}"/>
</Grid>
Now go to MainWindow.xaml file, add namespace
of CalculatorView.xaml file so that we can access CalculatorView.xaml in MainWindow
.
xmlns:views="clr-namespace:SimpleCommandDemoApp.Views"
Create a tag for CalculatorView.xaml view inside parent grid of MainWindow.xaml.
<Grid>
<views:CalculatorView/>
</Grid>
Step 3
Now we need to attach properties of two textboxes and label in CalculatorView.xaml to its ViewModel
called CalculatorViewModel
.
As we can see in XAML, we have bounded UI propertites with ViewModel
properties. CalculatorViewModel
's property “FirstValue
” is bounded with "Text
" property of first textbox
, CalculatorViewModel
's property “SecondValue
” is bounded with "Text
" property of second textbox
. And CalculatorViewModel
's property “Output
” is bounded with “Content
” property of label
.
To do Binding with CalculatorViewModel
, create three private
fields called firstValue
, secondValue
and output and three public
properties with the same name what we have given for binding of text property of the textbox
es and label
. We must provide the same names to three properties as we have used while binding for Text
property of textbox
es in UI.
Property “FirstValue
” is written as shown below, in a similar way, we have to create two more properties named as “SecondValue
” and “Output
” in CalculatorViewModel
.
public double FirstValue
{
get
{
return firstValue;
}
set
{
firstValue = value;
}
}
How to Use ICommand Interface
To bind Commands with UI Controls, we need to create a command
class which must implement ICommand
interface.
First, we would be creating a command
class for each button's functionality. Later, we will see how we can reuse a single generic command
class to handle those functionality. As of now, we will first create individual command
for "Add
" functionality.
Step 4
We have already created a “Plus” button on UI page. As we are following MVVM pattern, in this case to handle such kind of functionality, we need to implement ICommand
interface. Let us do that by writing the below code in PlusCommand
Class.
public class PlusCommand : ICommand
{
private CalculatorViewModel calculatorViewModel;
public PlusCommand(CalculatorViewModel vm)
{
calculatorViewModel = vm;
}
public bool CanExecute(object parameter)
{
return true;
}
public void Execute(object parameter)
{
calculatorViewModel.Add();
}
public event EventHandler CanExecuteChanged;
}
Step 5
Now create a private
field of PlusCommand
class in CalculatorViewModel
and create an instance of PlusCommand
class inside the constructor of CalculatorViewModel
.
private PlusCommand plusCommand;
public CalculatorViewModel()
{
plusCommand = new PlusCommand(this);
}
Step 6
Register namespace of CalculatorViewModel
to CalculatorView.xaml file. For that, the below line of code needs to be added in namespace
area.
xmlns:vm="clr-namespace:SimpleCommandDemoApp.ViewModels"
After namespaces, add UserControl.Resources
tag to register CalculatorViewModel
by specifying the key "calculatorVM
". Same key we have used while providing DataContext
Binding to the grid.
<UserControl.Resources>
<vm:CalculatorViewModel x:Key="calculatorVM" />
</UserControl.Resources>
Step 7
Implement Add
method in CalculatorViewModel
.
public void Add()
{
Output = firstValue + secondValue;
}
Step 8
Create a command named as “AddCommand
” name in CalculatorViewModel
. Command
’s name must be same as we have given for button's Command
property binding in CalculatorView.xaml file. Code for AddCommand
is shown below:
internal ICommand AddCommand
{
get
{
return plusCommand;
}
}
Step 9
Now run the application, click on “Plus” button, CalculatorViewModel
constructor will be called because we have given reference of CalculatorViewModel
in CalculatorView.xaml file as DataContext
. From the constructor of CalculatorViewModel
, we are creating the instance of PlusCommand
. While creating instance of PlusCommand
, we are passing CalculatorViewModel ViewModel
itself using “this
” keyword.
While execution of AddCommand
, first CanExecute
method will be called which will return "true
" as we have hardcoded it for simplicity. Then Execute
method will be called and it will invoke Add
method of CalculatorViewModel
.
Put the breakpoint to Add
method and run the application, we will see values entered into textboxes are available in firstValue
, secondValue
variables. And calculated result will be assigned to Output
property. But result is not visible on the screen in the content of label
. If we want to see the result on UI, we have to implement INotifyPropertyChanged Interface so that Change in "Output" property of ViewModel can be notified to UI.
Need of INotifyPropertyChanged
The purpose of INotifyPropertyChanged
is to notify if any changes happen to a property to all of its references (UI Controls/ViewModel). Since by default, UI properties (i.e., Text
property of Textbox
) mostly have INotifyPropertyChanged
implemented. Now we need to implement this interface for ViewModel
s too, so that if any change occurs in ViewModel
side, it can be notified/reflected to UI.
Step 10
As we have seen in the above step, “Output
” is the name of CalculatorViewModel
’s property, which we have bound to the Content
property of label
. When call comes to Add
method, we assign calculated value to “Output
” property. Since “Output
” is a public
property and bound to UI, this way change will be reflected to label
. Now with the help of INotifyPropertyChanged
, label
’s Content
will be updated.
So let us implement INotifyPropertyChanged
interface in ViewModelBase
class. The code is as shown below:
public class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
Step 11
Inherit CalculateViewModel
from ViewModelBase
, add one line of code inside the set block of all three public
properties as shown below:
OnPropertyChanged("FirstValue");
OnPropertyChanged
is a method which takes property name as argument. We have implemented this method in ViewModelBase
class. Whenever any change will occur in properties either from UI or ViewModel
, OnPropertyChanged
method will be called. Since we have written Mode=TwoWay
in XAML code for first textbox
and second textbox
, whenever there will be any change either at UI side or ViewModel
side, another party (UI or ViewModel
) will be notified.
Now run the application, we would be able to perform Add
operation and result will be visible in Output
label. We need to follow the same steps for the rest of the button click commands to achieve three more calculations.
Problem with Individual Commands
As of now, we need to create separate command classes for each operation. As we have done, for PlusCommand class, it has the following drawbacks:
First: PlusCommand
class is tightly coupled with CalculatorViewModel
because PlusCommand
class is having the reference of CalculatorViewModel
.
Second: From Execute
method, we are calling Add
method of CalculatorViewModel
. In future, if we change the name of Add
method, then we have to modify (Execute
method of) PlusCommand
class also.
Third: As we cannot reuse PlusCommand
class for other operations, so for every event, we need to write many different individual command classes for each operation. In our case, on “Plus” button click, we are calling Add method. But for “Minus” button click, we need to call Subtract
method, which we cannot do by using PlusCommand
Class. That is why we have created four Command
classes to handle each click event named as PlusCommand
, MinusCommand
, MultiplyCommand
and DivideCommand
, which is not a good approach.
That’s why we create a generic command class to handle all kind of operations. For that, we can use inbuilt delegates.
Generic Implementation of Command
There are many inbuilt delegates like Action
, Func
and Predicate
, etc. with .NET Framework. In our demo application, we will use Action
delegate. For more information about Action
, have a look here. Then we will see how to makes our work easy by increasing reusability.
Step 12
In the above steps, we have created four command classes to handle four button click event. Now by using Action
delegate, we will remove all of four command classes, by creating one generic command class called RelayCommand
. We can give any name instead of RelayCommand
. As a good practice, we should give some meaningful name. Write the below code in RelayCommand
class:
Now we need to change one line of code. Comment the first line and uncomment the second line of get
block of AddCommand
property as shown below:
public ICommand AddCommand
{
get
{
return new RelayCommand(Add);
}
}
Before returning from this get
block, the constructor of RelayCommand
will be called which takes a method as an Action
delegate. Here, we are passing name of Add
method to Action
delegate parameter.
Put the breakpoint on constructor of RelayCommand
and run the application. We will be able to see the name of Add
method in workToDo
local variable as shown below:
Now all four operations can be handled just by using RelayCommand
class. Now we can remove all of four command classes as we have created in folder "Commands\Specific".
Conclusion
In this article, we had a walkthrough to learn ICommand
Interface and its use. We understood how to use ICommand
interface to create generic Command
class as a standard practice of MVVM pattern. Thanks for reading. Your comments and suggestions for improvement are most welcome.
History
- 8th November, 2015: Initial version