Click here to Skip to main content
15,868,016 members
Articles / Desktop Programming / WPF

ICommand Interface in WPF

Rate me:
Please Sign up or sign in to vote.
4.91/5 (49 votes)
8 Nov 2015CPOL11 min read 107.3K   3.2K   39   35
ICommand interface and its use in generic implementation of Command
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 RoutedEvents 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 Commands. 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 Commands 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 textboxes 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 textboxes, 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:

Final Screen Shot of Demo App

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.

Application Solution Image

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.

XML
<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.

XML
xmlns:views="clr-namespace:SimpleCommandDemoApp.Views"

Create a tag for CalculatorView.xaml view inside parent grid of MainWindow.xaml.

XML
<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 textboxes and label. We must provide the same names to three properties as we have used while binding for Text property of textboxes 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.

C#
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.

C#
public class PlusCommand : ICommand
{
    // Creating private field of CalculatorViewModel
    // and passing calculatorViewModel into the constructor
    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.

C#
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.

XML
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.

XML
<UserControl.Resources>
    <vm:CalculatorViewModel x:Key="calculatorVM" />
</UserControl.Resources>

Step 7

Implement Add method in CalculatorViewModel.

C#
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:

C#
internal ICommand AddCommand
{
   get
   {
       return plusCommand;
       // return new RelayCommand(Add);
   }
}

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 ViewModels 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:

C#
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:

C#
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:

Code of 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:

C#
public ICommand AddCommand
    {
        get
        {
            //return plusCommand;
            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:

Code Execution of RelayCommand Class

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

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer
India India
I am a Software Developer working on Microsoft technologies. My interest is exploring and sharing the awesomeness of emerging technologies.

Comments and Discussions

 
Questionviews not recodgnized Pin
Member 1521124522-May-21 5:03
Member 1521124522-May-21 5:03 
PraiseI cannot thank you enough!! Pin
Member 1435422513-May-20 3:27
Member 1435422513-May-20 3:27 
QuestionMerci beacoup Pin
said0113-Apr-20 10:24
said0113-Apr-20 10:24 
Praisevery useful Pin
Member 1367122725-Mar-20 1:17
Member 1367122725-Mar-20 1:17 
QuestionWonderfully explained. Pin
Member 1466647024-Nov-19 4:33
Member 1466647024-Nov-19 4:33 
PraiseComprehensive Article on ICommand Pin
Member 1345943229-Jul-19 20:27
Member 1345943229-Jul-19 20:27 
This article is very precise and comprehensive on ICommand interface. It is written even better than books. Although it doesn't implement MVVM pattern completely but probably its is more about ICommand than MVVM.
Really Appreciate the effort.
Umar

QuestionRelayCommand not in the framework. Pin
Member 1450762520-Jun-19 22:37
Member 1450762520-Jun-19 22:37 
QuestionMost beautiful and useful article in code project I ever seen. Pin
Member 1412942127-Jan-19 3:25
Member 1412942127-Jan-19 3:25 
Questioninternal Command AddCommand must be public Pin
Member 128874599-Jan-19 3:10
Member 128874599-Jan-19 3:10 
GeneralMy vote of 5 Pin
sbarnes13-Oct-18 20:08
sbarnes13-Oct-18 20:08 
QuestionOne little problem ... Pin
Francesco La Gamba30-Jun-18 5:57
Francesco La Gamba30-Jun-18 5:57 
GeneralNice Pin
Kishore Kishh10-May-18 8:59
Kishore Kishh10-May-18 8:59 
QuestionGood! Pin
Member 84219082-Mar-18 3:35
Member 84219082-Mar-18 3:35 
SuggestionUse of delegates Pin
niksofteng16-Feb-18 5:16
niksofteng16-Feb-18 5:16 
QuestionOne of the Nice Article - I ever Read Pin
Member 1235327626-Jan-18 22:39
Member 1235327626-Jan-18 22:39 
QuestionYou're a natural! Pin
Müdürüm15-Nov-17 6:51
Müdürüm15-Nov-17 6:51 
PraiseDetailed explanation Pin
Member 116515089-Oct-17 4:42
Member 116515089-Oct-17 4:42 
AnswerRe: Detailed explanation Pin
Snesh Prajapati9-Oct-17 7:47
professionalSnesh Prajapati9-Oct-17 7:47 
QuestionVery nice and useful article! One question - How to do action specific validation in CanExecute()? Pin
Member 115352108-May-17 20:05
Member 115352108-May-17 20:05 
QuestionAwesome article.! Pin
Park JunYoung15-Mar-17 21:45
Park JunYoung15-Mar-17 21:45 
QuestionComplete understanding of mvvm and Icommand Pin
Member 110426996-Feb-17 20:45
Member 110426996-Feb-17 20:45 
GeneralWonderful article. Pin
sumitk.cadc20-Nov-16 17:43
sumitk.cadc20-Nov-16 17:43 
AnswerRe: Wonderful article. Pin
Snesh Prajapati21-Nov-16 5:04
professionalSnesh Prajapati21-Nov-16 5:04 
PraiseWell done! Pin
Member 1268465713-Aug-16 13:51
Member 1268465713-Aug-16 13:51 
AnswerRe: Well done! Pin
Snesh Prajapati13-Aug-16 14:56
professionalSnesh Prajapati13-Aug-16 14:56 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.