#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"/>
Advertisement

#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

#1,083 – Setting CommandBindings in XAML

You can configure command bindings in code-behind, adding a CommandBinding object to a top-level window’s CommandBindings collection, as follows:

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

            this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Open,
                Executed_Open, CanExecute_Open));
        }

You can set this command binding up in XAML, rather than in code-behind.  Below is an example of doing the same binding in XAML.

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

    <StackPanel>
        <Button Content="Open" Command="ApplicationCommands.Open"
                Margin="10" Padding="10,3"
                HorizontalAlignment="Center" />
        <CheckBox Content="Can Open" IsChecked="{Binding CanOpenIsChecked}"
                  Margin="10"/>
    </StackPanel>
</Window>

This assumes that you’ve defined the following methods in code-behind:

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

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

#1,082 – Adding CommandBindings to Individual UI Elements

Before using a routed command, you need to associated a particular command object with code for the Execute and CanExecute methods.  You do this by creating a CommandBinding object that binds the command to the code.  You then typically add that CommandBinding to the CommandBindings collection for the top-level window.

If you want to use the same command object, but bind it to different executable code for different UI elements, you can instead add the CommandBinding objects to the CommandBindings for individual elements.  In the code below, we create two different bindings for the ApplicationCommands.Open command.

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

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

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

1082-001
1082-002

#1,081 – Adding CommandBinding to Top-Level CommandBindings

In the example below, we bind the ApplicationCommands.Open command to some custom code by adding a CommandBinding instance to the top-level window’s CommandBindings property.

        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; }));
        }

We can now bind the Command property of any UI element under the top-level window to the ApplicationCommands.Open command.  Below, we bind two different buttons to the Open command.  Clicking on either button will result in execution of the same lambda expression.

<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">

    <StackPanel>
        <Button Content="Open A" Command="ApplicationCommands.Open"
                Margin="10" Padding="10,3"
                HorizontalAlignment="Center" />
        <Button Content="Open B" Command="ApplicationCommands.Open"
                Margin="10" Padding="10,3"
                HorizontalAlignment="Center" />
        <CheckBox Content="Can Open" IsChecked="{Binding CanOpenIsChecked}"
                  Margin="10"/>
    </StackPanel>
</Window>

1081-001

#1,080 – Command Text for Preexisting Commands Is Automatically Localized

If you use any of the preexisting RoutedUICommand objects in your application, the Text property of the command is automatically localized to match the language of the operating system that you’re running on.

Assume that you wire a Button up to an Open command:

        <Button Content="{Binding RelativeSource={RelativeSource Self}, Path=Command.Text}"
                Command="ApplicationCommands.Open" />

If we run the application, the button text is in English.

1080-001

If we run the application on a French version of Windows, the text on the button will be localized.  Assuming that we have the proper language pack installed, we can also just override the CurrentUICulture of the current thread.

    public partial class App : Application
    {
        public App()
        {
           Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR");
        }
    }

Now when we run the application, the word “Open” is translated to French.
1080-002

#1,079 – Executing a Command Programmatically

You normally bind the Command property of a user interface element to a routed command to have the command automatically executed when the user interacts with the user interface element.

You can also execute commands programmatically by calling their Execute method.  Note that the command will do nothing if CanExecute is returning false.

        <Button Content="Do Something" Click="Button_Click"
                Margin="10" HorizontalAlignment="Center"/>
        <CheckBox Content="Can Open" IsChecked="{Binding CanOpenIsChecked}"
                  Margin="10"/>
    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;

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

        // INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        private void RaisePropertyChanged(string propName)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }

        public bool CanOpenIsChecked { get; set; }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            // Execute command programmatically
            if (ApplicationCommands.Open.CanExecute(null, null))
                ApplicationCommands.Open.Execute(null, null);
            else
                MessageBox.Show("No no no!");
        }
    }

1079-001
 

#1,078 – Defining a Command Binding Using Lambda Expressions

Recall that commands in WPF are objects that you bind UI elements to and that are in turn bound to code for executing the command and for knowing whether a command can be executed.

Below is an example that sets up a command binding using lambda expressions.

    <Window.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Open" Command="ApplicationCommands.Open"/>
        </ContextMenu>
    </Window.ContextMenu>

    <StackPanel>
        <Button Content="Open" Command="ApplicationCommands.Open"
                Margin="10" HorizontalAlignment="Center" />
        <CheckBox Content="Can Open" IsChecked="{Binding CanOpenIsChecked}"
                  Margin="10"/>
    </StackPanel>

We set up the command binding in the window’s constructor.

    public partial class MainWindow : Window, INotifyPropertyChanged
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = this;

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

        // INotifyPropertyChanged
        public event PropertyChangedEventHandler PropertyChanged = delegate { };

        private void RaisePropertyChanged(string propName)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propName));
        }

        public bool CanOpenIsChecked { get; set; }
    }

1078-001
1078-002