Delegate Commands

  • 7 minutes to read

Delegate commands are an implementation of the System.Windows.Input.ICommand interface, so they can be used to create commands in a ViewModel. A delegate command calls methods (delegates) that you assigned to the command when the command's Execute and CanExecute logic is invoked.

The following delegate commands are available.

  • DelegateCommand<T> - Specifies a command whose Execute and CanExecute delegates accept a single parameter of type T.
  • DelegateCommand - Specifies a command whose Execute and CanExecute delegates do not have any parameters.

Creating DelegateCommands

Both commands support two constructors: a constructor that accepts an Execute delegate, and a constructor that accepts Execute and CanExecute delegates.

public class DelegateCommandsViewModel : ViewModelBase {
    public DelegateCommand  DelegateCommand1 { get; private set; }
    public DelegateCommand<string> DelegateCommand2 { get; private set; }

    public DelegateCommandsViewModel() {
        DelegateCommand1 = new DelegateCommand(
            () => MessageBoxService.Show("This is a DelegateCommand"));

        DelegateCommand2 = new DelegateCommand<string>(
            x => MessageBoxService.Show(x), 
            x => !string.IsNullOrEmpty(x));
    }
}

CommandParameter Conversion

A DelegateCommand<T> automatically converts the command argument to the parameterized type if possible. In the example below, the CommandParameter (the "Text" string) will be automatically converted to the DocumentType parametrized type.

<Button Command="{Binding ShowDocumentCommand}" CommandParameter="Text"/>
public enum DocumentType { Text, Data }

public class DelegateCommandsViewModel : ViewModelBase {
    public DelegateCommand<DocumentType> ShowDocumentCommand { get; private set; }

    public DelegateCommandsViewModel() {
        ShowDocumentCommand = new DelegateCommand<DocumentType>(ShowDocument);
    }
    void ShowDocument(DocumentType parameter) {
        if(parameter == DocumentType.Text) {
            //... 
        }
        if(parameter == DocumentType.Data) {
            //... 
        }
    }
}

Updating Commands

The DelegateCommand constructors have an optional useCommandManager parameter. This parameter specifies whether a DelegateCommand uses the CommandManager to raise the CanExecuteChanged event. By default, useCommandManager is true, making it unnecessary to manually implement the disable/enable logic for your commands. Once you set the CanExecute delegate for the command, the delegate is automatically triggered when an end user interacts with the UI. When the CommandManager is used for this purpose, the CanExecute handler is called frequently, so avoid performing time-consuming operations in the delegate.

If you pass false as the last constructor argument, the CommandManager is not used. In this case, update your command by calling the RaiseCanExecuteChanged method.

public class DelegateCommandsViewModel : ViewModelBase {
    public DelegateCommand GoBackCommand{ get; private set; }
    public DelegateCommand GoForwardCommand { get; private set; }

    public DelegateCommandsViewModel() {
        GoBackCommand = new DelegateCommand(GoBack, CanGoBack, false);
        GoForwardCommand = new DelegateCommand(GoForward, CanGoForward, false);
    }

    void GoBack() {
        //... 
        UpdateCommandsState();
    }
    void GoForward() {
        //... 
        UpdateCommandsState();
    }
    bool CanGoBack() {
        //... 
    }
    bool CanGoForward() {
        //... 
    }
    void UpdateCommandsState() {
        GoBackCommand.RaiseCanExecuteChanged();
        GoForwardCommand.RaiseCanExecuteChanged();
    }
}

DelegateCommands in POCO

In a POCO View Model, DelegateCommands can be automatically generated based on public methods (with one parameter or none) of your View Model.

For instance, for the following Save and CanSave methods...

[POCOViewModel]
public class ViewModel {
    public void Save(string fileName) {
        //... 
    }
    public bool CanSave(string fileName) {
        return !string.IsNullOrEmpty(fileName);
    }
}

...the following SaveCommand property is automatically generated.

DelegateCommand<string> saveCommand;
public DelegateCommand<string> SaveCommand {
    get {
        return saveCommand ?? 
            (saveCommand = new DelegateCommand<string>(Save, CanSave));
    }
}

To update an automatically generated command in a POCO View Model, use the RaiseCanExecuteChanged extension method available from the DevExpress.Mvvm.POCO.POCOViewModelExtensions class.

[POCOViewModel]
public class ViewModel {
    public void GoBack(){
        //...
    }
    public bool CanGoBack(){
        //...
    }
    public void UpdateSaveCommand(){
        this.RaiseCanExecuteChanged(c => c.GoBack());
    }
}

Example

This example demonstrates how to create commands with the DelegateCommand class.

NOTE

A complete sample project is available at https://github.com/DevExpress-Examples/how-to-use-delegatecommand-e5165.

<UserControl x:Class="Example.View.MainView"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:ViewModel="clr-namespace:Example.ViewModel"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d" d:DesignHeight="500" d:DesignWidth="600">
    <UserControl.DataContext>
        <ViewModel:MainViewModel/>
    </UserControl.DataContext>

    <Grid x:Name="LayoutRoot" Background="White">
        <StackPanel Orientation="Vertical">
            <StackPanel Orientation="Horizontal" Margin="10">
                <Button Content="AutoUpdateCommand" Command="{Binding AutoUpdateCommand}" 
                        Margin="3" VerticalAlignment="Center"/>
                <CheckBox Content="IsAutoUpdateCommandEnabled" IsChecked="{Binding IsAutoUpdateCommandEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                          Margin="3" VerticalAlignment="Center"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Margin="10">
                <Button Content="ManualUpdateCommand" Command="{Binding ManualUpdateCommand}"
                        Margin="3" VerticalAlignment="Center"/>
                <CheckBox Content="IsManualUpdateCommandEnabled" IsChecked="{Binding IsManualUpdateCommandEnabled, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
                          Margin="3" VerticalAlignment="Center"/>
                <Button Content="ForceUpdateManualUpdateCommand" Command="{Binding ForceUpdateManualUpdateCommand}"
                        Margin="3" VerticalAlignment="Center"/>
            </StackPanel>
            <StackPanel Orientation="Horizontal" Margin="10">
                <TextBox Text="Message" x:Name="message" Width="80"/>
                <Button Content="CommandWithParameter" Command="{Binding CommandWithParameter}" CommandParameter="{Binding ElementName=message, Path=Text}"
                        Margin="3" VerticalAlignment="Center"/>
            </StackPanel>
        </StackPanel>
    </Grid>
</UserControl>