#1,090 – Sender vs. Source in CommandBinding Event Handlers

When handling a command’s Executed or CanExecute events, you can check the ExecutedRoutedEventArgs.Source or CanExecuteRoutedEventArgs.Source properties to get at the control that is the originator of the event.  But the event handler also includes a sender parameter that in many cases also points to the originator of the event.

The difference is:

  • The Source property refers to the originator of the event
  • The sender parameter refers to the object that owns the event handler

In the example below, clicking on the Button initiates a Paste command, which is bound to code using the parent Window’s CommandBindings property.

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Commands" Width="320" Height="220">

    <Window.CommandBindings>
        <CommandBinding Command="ApplicationCommands.Paste"
                        CanExecute="Paste_CanExecute"
                        Executed="Paste_Executed"/>
    </Window.CommandBindings>

    <StackPanel>
        <Button Content="Paste"
                Command="ApplicationCommands.Paste"
                Margin="10" Padding="10,3"
                HorizontalAlignment="Center" />
    </StackPanel>
</Window>

The Button is the Source of the routed command and the main Window is the sender.

1090-001

Advertisements

#1,089 – Adding a Parameter to a Command

When you set the Command property of a user interface element, you’re binding that element to a particular command.  The command, in turn, is associated with some code through its Executed property.

You can specify a command parameter using the CommandParameter property.  The data in this property will be passed to the code that runs when the command executes.

The XAML fragment below shows two buttons that both bind to the same command, but pass in different data.

        <Button Content="Open A"
                Command="ApplicationCommands.Open"
                CommandParameter="File A"
                Margin="10" Padding="10,3"
                HorizontalAlignment="Center" />
        <Button Content="Open B"
                Command="ApplicationCommands.Open"
                CommandParameter="File B"
                Margin="10" Padding="10,3"
                HorizontalAlignment="Center" />

We can then read that parameter in the code bound to the command’s Executed property.

        public void Executed_Open(object sender, ExecutedRoutedEventArgs e)
        {
            MessageBox.Show(string.Format("Executing Open command for [{0}]", e.Parameter));
        }

1089-001

#1,088 – Removing Key Bindings

You’ll sometimes discover that there are built-in key bindings that you want to get rid of.  If you define the KeyBinding shown below, you’ll discover that the Ctrl+Alt+O key sequence works to execute the Open command, as expected.  But the Ctrl+O sequence also appears to do the same thing.

    <Window.CommandBindings>
        <CommandBinding Command="ApplicationCommands.Open"
                        Executed="Executed_Open"
                        CanExecute="CanExecute_Open"/>
    </Window.CommandBindings>
    <Window.InputBindings>
        <KeyBinding Command="ApplicationCommands.Open"
                    Gesture="Ctrl+Alt+O"/>
    </Window.InputBindings>

Ctrl+O is automatically defined as an existing key binding that binds to the ApplicationCommands.Open command.  You can remove it by binding Ctrl+O to the ApplicationCommands.NotACommand command.  Ctrl+O will no longer be associated with the Open command.

        <Window.InputBindings>
            <KeyBinding Command="ApplicationCommands.Open"
                        Gesture="Ctrl+Alt+O"/>
            <KeyBinding Command="ApplicationCommands.NotACommand"
                        Gesture="Ctrl+O"/>
        </Window.InputBindings>

#1,087 – Associating a Key Binding with Multiple Modifier Keys

You define a KeyBinding object to bind a key gesture (i.e. keypress) to a particular command.  You can do this in XAML by defining a <KeyBinding> element, associating a routed command with a key “gesture”.  The gesture indicates the key that you can press in order to execute the command.

Key gestures typically require associating a key with at least one of the modifier keys (Ctrl, Alt, Shift, or Windows key).  For example, Ctrl+O is specified as:

        <KeyBinding Command="ApplicationCommands.Open"
                    Gesture="Ctrl+O"/>

You can also combine modifier keys, using the “+” symbol.

        <KeyBinding Command="ApplicationCommands.Open"
                    Gesture="Ctrl+Alt+O"/>

#1,086 – Defining a Key Binding in XAML

You define a KeyBinding object to bind a key gesture (i.e. keypress) to a particular command.  You can do this in code by creating a KeyBinding instance and adding it to an UI elements InputBindings collection.

You can also define a key binding in XAML, as shown below.  You use a <KeyBinding> element for each key binding.

<Window x:Class="WpfApplication1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Commands" Width="320" Height="220">

    <Window.CommandBindings>
        <CommandBinding Command="ApplicationCommands.Open"
                        Executed="Executed_Open"
                        CanExecute="CanExecute_Open"/>
    </Window.CommandBindings>
    <Window.InputBindings>
        <KeyBinding Command="ApplicationCommands.Open"
                    Gesture="Ctrl+O"/>
    </Window.InputBindings>

    <StackPanel/>
</Window>

Here is the code-behind, containing methods for Executed and CanExecute.

        public void Executed_Open(object sender, ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("Executing the Open command");
        }

        public void CanExecute_Open(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;
        }

#1,085 – Input Bindings Don’t Require that Element Binds to Command

When binding a routed command in WPF to a user interface element, you typically do the following:

  • Create a CommandBinding instance that associates a command to executable code
  • Add the CommandBinding to the element’s CommandBindings collection (typically belonging to the top-level window)
  • Set the Command property of an individual user interface element to refer to the Command

When you define InputBindings, you must perform the first two steps listed above.  You do not have to set the Command property of any user interface element in order for the input binding to work.

Consider the following example:

  • We bind a command to some code by creating a CommandBinding
  • We add the CommandBinding to a window’s CommandBindings collection
  • We define a KeyBinding for the same command and add to window’s InputBindings

We can now execute the command using the key, even though we didn’t set the Command property for any UI element.

#1,084 – A KeyBinding Binds a Command to a Key

A user interface element has a CommandBindings collection containing command binding objects that indicate which commands are supported for the element and the code that the command is bound to.

User interface elements also have an InputBindings collection that contains KeyBinding and MouseBinding instances, each of which maps keyboard or mouse input to a command that is also present in the CommandBindings collection.

In the code below, we wire up the Open command for both key (Ctrl+O) and mouse (Ctrl+Left Click) input.

        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;

            this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Open,
               (sender, e) => { MessageBox.Show("Executing the Open command"); },
               (sender, e) => { e.CanExecute = CanOpenIsChecked; }));

            // Ctrl+O = Open
            this.InputBindings.Add(new KeyBinding(ApplicationCommands.Open,
                new KeyGesture(Key.O, ModifierKeys.Control)));

            // Ctrl+Left Mouse Click = Open
            this.InputBindings.Add(new MouseBinding(ApplicationCommands.Open,
                new MouseGesture(MouseAction.LeftClick, ModifierKeys.Control)));
        }

We can now use either form of input to execute the Open command.

1084-001