#1,199 – Complete WPF Command Example

Below is a cheat sheet for creating a custom command in WPF.

Use a static property to expose a command object from the ViewModel or code-behind. RoutedUICommand allows for associating control text with the command itself.

private static RoutedUICommand _pressMeCommand = 
    new RoutedUICommand("Press Me", "PressMe", typeof(MainWindow));
public static RoutedUICommand PressMeCommand
{
    get { return _pressMeCommand; }
}

Add command handlers (in code-behind or ViewModel).

private void PressMe_CanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = CowboyCanTalk;
}
 
private void PressMe_Executed(object sender, ExecutedRoutedEventArgs e)
{
    MessageBox.Show("Howdy howdy I'm a cowboy");
}

Bind the command to its handlers, done here in XAML for a window.

<Window.CommandBindings>
    <CommandBinding Command="local:MainWindow.PressMeCommand" 
                    CanExecute="PressMe_CanExecute" 
                    Executed="PressMe_Executed"/>
</Window.CommandBindings>

Wire a button up to the command. Note use of command’s Text property for the button’s Content (text).

<Button Command="local:MainWindow.PressMeCommand" 
        Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}" />

We can also wire up the command to other GUI elements, e.g. a menu item in a context menu. The menu item’s text is set up automatically.

<Window.ContextMenu>
    <ContextMenu>
        <MenuItem Command="{x:Static local:MainWindow.PressMeCommand}" />
    </ContextMenu>
</Window.ContextMenu>

#1,097 – Getting Items in Context Menu to Correctly Use Command Binding

Let’s say that you set up command bindings for a main Window in an application and then use the command for some control (e.g. a Button) and also within a ContextMenu.  (Assume that the GreetUser_CanExecute method always returns true).

    <Window.CommandBindings>
        <CommandBinding Command="{x:Static loc:MainWindow.GreetUserCommand}"
                        CanExecute="GreetUser_CanExecute"
                        Executed="GreetUser_Executed"/>
    </Window.CommandBindings>

    <Window.ContextMenu>
        <ContextMenu>
            <MenuItem Command="{x:Static loc:MainWindow.GreetUserCommand}"/>
        </ContextMenu>
    </Window.ContextMenu>

    <StackPanel>
        <TextBox Name="txtSomeText"
                 Width="220" Height="25" Margin="10"/>
        <Button HorizontalAlignment="Center"
                Padding="10,5" Margin="10"
                Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"
                Command="{x:Static loc:MainWindow.GreetUserCommand}"/>
    </StackPanel>

If you run this code and right-click on the window to bring up the context menu, the MenuItem is greyed out.  It’s not binding correctly to our CanExecute method.  The Button, on the other hand, did find the binding.

1097-001

The fix for this is to set the CommandTarget for the MenuItem to the PlacementTarget of the parent ContextMenu–the Window.  The MenuItem definition becomes:

            <MenuItem Command="{x:Static loc:MainWindow.GreetUserCommand}"
                      CommandTarget="{Binding Path=PlacementTarget, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"/>

1097-002