Click here to Skip to main content
15,867,594 members
Articles / Desktop Programming / WPF

How to use Commands in WPF

Rate me:
Please Sign up or sign in to vote.
4.61/5 (39 votes)
24 Oct 2013CPOL3 min read 330.3K   10.4K   67   30
This article shows how to use WPF Commands.

Introduction

In this article, we will talk about WPF Commands. When I develop a new application in WPF, I try to follow the MVVM Pattern (Model-View-ViewModel). To help me with it, I use the toolkit shared by Laurent Bugnion: MVVM Light Toolkit (Galasoft). The idea is the same with or without a toolkit.

Using the code

To show you how to use commands, we will create a simple application that saves some information about a person.

So a person can be described using these fields:

  • LastName
  • FirstName
  • Address
  • ZipCode
  • City

A Save button would call the SaveCommand and the Cancel button would call CancelCommand. We first create our model, adding a Person class in the Model directory. Keep things simple: 

C#
public class Person
{
    public string LastName { get; set; }
    public string FirstName { get; set; }
    public string Address { get; set; }
    public string ZipCode { get; set; }
    public string City { get; set; }
} 

Then we create our ViewModel: I will simply modify the one created by the template for MainWindow. I just edit it to add the properties needed:

C#
public class MainViewModel : ViewModelBase
{
    private readonly Person _newPerson;

    private const string LastNamePropertyName = "LastName";
    public string LastName
    {
        get { return _newPerson.LastName; }
        set
        {
            _newPerson.LastName = value;
            RaisePropertyChanged(LastNamePropertyName);
        }
    }

    private const string FirstNamePropertyName = "FirstName";
    public string FirstName
    {
        get
        {
            return _newPerson.FirstName;
        }
        set
        {
            _newPerson.FirstName = value;
            RaisePropertyChanged(FirstNamePropertyName);
        }
    }

    private const string AddressPropertyName = "Address";
    public string Address
    {
        get
        {
            return _newPerson.Address;
        }
        set
        {
            _newPerson.Address = value;
            RaisePropertyChanged(AddressPropertyName);
        }
    }

    private const string ZipCodePropertyName = "ZipCode";
    public string ZipCode
    {
        get
        {
            return _newPerson.ZipCode;
        }
        set
        {
            _newPerson.ZipCode = value;
            RaisePropertyChanged(ZipCodePropertyName);
        }
    }

    private const string CityPropertyName = "City";
    public string City
    {
        get
        {
            return _newPerson.City;
        }
        set
        {
            _newPerson.City = value;
            RaisePropertyChanged(CityPropertyName);
        }
    }

    ///
    /// Initializes a new instance of the MainViewModel class.
    ///
    public MainViewModel()
    {
        _newPerson = new Person();
    }
}

Let's create the UI. We will have a simple form in MainWindow.xaml:

XML
<Grid Height="195">
    <Grid.RowDefinitions>
        <RowDefinition Height="30" />
        <RowDefinition Height="30" />
        <RowDefinition Height="30" />
        <RowDefinition Height="30" />
        <RowDefinition Height="30" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="42*" />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="122*" />
        <ColumnDefinition Width="296*" />
    </Grid.ColumnDefinitions>
    <Label Content="LastName" Grid.RowSpan="2" Height="28" HorizontalAlignment="Left" 
       Margin="40,5,0,0" Name="label1" VerticalAlignment="Top" />
    <Label Content="FirstName" Grid.Row="1" Grid.RowSpan="2" Height="28" 
       HorizontalAlignment="Left" Margin="40,5,0,0" Name="label2" 
       VerticalAlignment="Top" />
    <Label Content="Address" Grid.Row="2" Grid.RowSpan="2" Height="28" 
       HorizontalAlignment="Left" Margin="40,5,0,0" 
       Name="label3" VerticalAlignment="Top" />
    <Label Content="Code Postal" Grid.Row="3" Grid.RowSpan="2" 
       Height="28" HorizontalAlignment="Left" Margin="40,5,0,0" 
       Name="label4" VerticalAlignment="Top" />
    <Label Content="City" Grid.Row="4" Grid.RowSpan="3" Height="28" 
       HorizontalAlignment="Left" Margin="40,5,0,0" 
       Name="label5" VerticalAlignment="Top" />
    <TextBox Grid.Column="1" Grid.RowSpan="2" Height="23" HorizontalAlignment="Left" 
       Margin="20,5,0,0" Name="textBox1" VerticalAlignment="Top" 
       Width="120" Text="{Binding Path=LastName}" />
    <TextBox Grid.Column="1" Grid.Row="1" Grid.RowSpan="2" Height="23" 
       HorizontalAlignment="Left" Margin="20,5,0,0" Name="textBox2" 
       VerticalAlignment="Top" Width="120" Text="{Binding Path=FirstName}" />
    <TextBox Grid.Column="1" Grid.Row="2" Grid.RowSpan="2" Height="23" 
       HorizontalAlignment="Left" Margin="20,5,0,0" Name="textBox3" 
       VerticalAlignment="Top" Width="120" Text="{Binding Path=Address}" />
    <TextBox Grid.Column="1" Grid.Row="4" Height="23" HorizontalAlignment="Left" 
       Margin="20,5,0,0" Name="textBox4" VerticalAlignment="Top" 
       Width="120" Text="{Binding Path=City}" />
    <TextBox Grid.Column="1" Grid.Row="3" Grid.RowSpan="2" Height="23" 
       HorizontalAlignment="Left" Margin="20,5,0,0" Name="textBox5" 
       VerticalAlignment="Top" Width="120" Text="{Binding Path=ZipCode}" />
    <Button Content="Save" Grid.Column="1" Grid.Row="6" Height="23" 
       HorizontalAlignment="Left" Margin="25,10,0,0" Name="button1" 
       VerticalAlignment="Top" Width="75" />
    <Button Content="Cancel" Grid.Column="1" Grid.Row="6" Height="23" 
       HorizontalAlignment="Left" Margin="120,10,0,0" Name="button2" 
       VerticalAlignment="Top" Width="75" />
</Grid>

Here is what it should look like:

Now, the main reason for this article: the Commands. We will create our two commands and then bind them to our buttons. How do we define a command? First, the command should implement the ICommand interface. Then, a Create method will create the command so that we can use it. Then, we find two methods: the first one, CanExecute, would check if the command can be executed, and the second one, Execute, will execute the command.

The Save Command:

C#
public ICommand SaveCommand
{
    get;
    internal set;
}

private bool CanExecuteSaveCommand()
{
    return !string.IsNullOrEmpty(LastName);
}

private void CreateSaveCommand()
{
    SaveCommand = new RelayCommand(SaveExecute, CanExecuteSaveCommand);
}

public void SaveExecute()
{
    Person.Save(_newPerson);
}

If we look at the CanExecute method, we can see that the execution would be allowed only if there is a last name.

We now add the creation of the method in the constructor of our ViewModel:

C#
public MainViewModel()
{
    _newPerson = new Person();
    CreateSaveCommand();
}

And we bind our command to the Save button:

XML
<Button Content="Save" Grid.Column="1" Grid.Row="6" Height="23" 
   HorizontalAlignment="Left" Margin="25,10,0,0" 
   Name="button1" VerticalAlignment="Top" 
   Width="75" Command="{Binding Path=SaveCommand}" />

Let's launch the application and test this command.

When the application launches, the LastName is, of course, empty. And you can see that the Save button is disabled and we cannot save:

We add a last name and set the focus on the following textbox and we can observe that the Save button is now enabled. The condition in the CanExecute returns true!

If we delete the last name and change focus, the button will be disabled again.

Now, we add the Cancel command. It works the same way as the Save command but there is no requirement to allow the action. So, we will not use the CanExecute method:

C#
public ICommand CancelCommand
{
    get;
    internal set;
}

private void CreateCancelCommand()
{
    CancelCommand = new RelayCommand(CancelExecute);
}

public void CancelExecute()
{
    LastName = string.Empty;
    FirstName = string.Empty;
    Address = string.Empty;
    ZipCode = string.Empty;
    City = string.Empty;
}

In the Execute method, we empty all the textboxes. Fill in the information and click on the Cancel button, all the textboxes will be cleared. Don't forget to call the CreateCancelCommand method in the constructor and to bind the command to the Cancel command. The constructor:

C#
public MainViewModel()
{
    _newPerson = new Person();
    CreateSaveCommand();
    CreateCancelCommand();
}

Cancel button binding:

XML
<Button Content="Cancel" Grid.Column="1" Grid.Row="6" Height="23" 
   HorizontalAlignment="Left" Margin="120,10,0,0" Name="button2" VerticalAlignment="Top" 
   Width="75" Command="{Binding Path=CancelCommand}" />

This is a very simple example of how to use Commands in WPF. Let's try it!

Points of Interest

WPF Commands are really useful in multiple ways. Here you saw how to use it and now you can try to discover what can be done with them.

History

  • August 9th, 2011: First post.

License

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


Written By
Architect
France France
I'm coding in .Net since 9 years, most with ASP.Net and SharePoint and a little using WPF, MVC, Windows Phone 8 and WinRT technology.
I have learned so much reading others experience and tutorials, or tips so I try to do the same, keeping learning from others of course.
You can also find my blog here : http://sharemstips.wordpress.com/

Comments and Discussions

 
GeneralMy vote of 2 Pin
Niels Peter Gibe16-Mar-23 5:49
Niels Peter Gibe16-Mar-23 5:49 
Questionexample not working Pin
Member 1382056510-May-18 0:14
Member 1382056510-May-18 0:14 
GeneralExcellent Article! Pin
Member 770723820-Mar-17 23:56
Member 770723820-Mar-17 23:56 
Bug[My vote of 1] does any one able to run it? Pin
Member 118161166-Oct-16 22:05
Member 118161166-Oct-16 22:05 
GeneralRe: [My vote of 1] does any one able to run it? Pin
Member 1382056510-May-18 0:14
Member 1382056510-May-18 0:14 
QuestionError Pin
Member 116049738-Jul-15 1:09
Member 116049738-Jul-15 1:09 
AnswerRe: Error Pin
Member 1233893121-Feb-16 6:23
Member 1233893121-Feb-16 6:23 
QuestionWhere is ViewModelBase? Pin
azamsharp10-Jul-14 8:28
azamsharp10-Jul-14 8:28 
QuestionRelayCommand Implementation PinPopular
Member 930797820-May-14 17:05
Member 930797820-May-14 17:05 
Question[My vote of 1] Poor Example Pin
SledgeHammer0124-Oct-13 5:05
SledgeHammer0124-Oct-13 5:05 
AnswerRe: [My vote of 1] Poor Example Pin
daveslc15-Jan-14 6:07
daveslc15-Jan-14 6:07 
AnswerRe: [My vote of 1] Poor Example Pin
Devoney27-Nov-14 9:03
Devoney27-Nov-14 9:03 
GeneralRe: [My vote of 1] Poor Example Pin
SledgeHammer0127-Nov-14 10:48
SledgeHammer0127-Nov-14 10:48 
GeneralMy vote of 5 Pin
fredatcodeproject24-Oct-13 2:21
professionalfredatcodeproject24-Oct-13 2:21 
Questionmmmh Pin
Member 102086142-Sep-13 8:25
Member 102086142-Sep-13 8:25 
errrrrrrors plz fix themMad | :mad:
AnswerRe: mmmh Pin
Nadege Rouelle23-Oct-13 22:41
Nadege Rouelle23-Oct-13 22:41 
QuestionError in the code , Pin
Sujeet Bhujbal6-Mar-13 19:23
Sujeet Bhujbal6-Mar-13 19:23 
AnswerRe: Error in the code , Pin
Nadege Rouelle6-Mar-13 21:58
Nadege Rouelle6-Mar-13 21:58 
AnswerRe: Error in the code , Pin
Member 1022371121-Aug-13 8:55
Member 1022371121-Aug-13 8:55 
GeneralRe: Error in the code , Pin
Nadege Rouelle23-Oct-13 22:41
Nadege Rouelle23-Oct-13 22:41 
QuestionSource code does not compile Pin
mackan7020-Dec-12 1:40
mackan7020-Dec-12 1:40 
AnswerRe: Source code does not compile Pin
Nadege Rouelle6-Mar-13 21:59
Nadege Rouelle6-Mar-13 21:59 
QuestionHow about CommandBinding? Pin
Khanh Hua25-Sep-12 15:12
Khanh Hua25-Sep-12 15:12 
QuestionWhy the Save Button can't be Enabled after I fill in last name Pin
davidsun11111-Jul-12 8:42
davidsun11111-Jul-12 8:42 
GeneralMy vote of 4 Pin
Jalal Khordadi16-Jan-12 10:20
Jalal Khordadi16-Jan-12 10:20 

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.