#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

#1,077 – Checking for Single Modifer vs. Multiple Modifier Keys

In keypress events, you can check to see if the user is also holding down one of the modifier keys (Ctrl, Alt, Shift, or Windows key).  You do this by checking the KeyEventArgs.KeyboardDevice.Modifiers property.

You sometimes want to check to see if one and only one modifier key is being held down (e.g. Ctrl key without Alt, Shift, or Windows).  You do this by checking to see if the Modifiers property is equal to one of the ModifierKeys enumerated values.

            if ((e.Key == Key.G) &&
                (e.KeyboardDevice.Modifiers == ModifierKeys.Control))
                MessageBox.Show("Ctrl+G detected, NO Alt/Shift/Windows");

You may also want to check to see if the control key is being pressed, either alone or in conjunction with one of the other modifier keys.  You do this by using a mask.

            if ((e.Key == Key.G) &&
                ((e.KeyboardDevice.Modifiers & ModifierKeys.Control) == ModifierKeys.Control))
                MessageBox.Show("Ctrl+G or Ctrl+Alt+G, Ctrl+Alt+Windows+G, etc.");

#1,076 – Two Ways to Check for Use of Modifier Keys in Keypress Handlers

You can check for the presence of modifier keys (e.g. Alt, Ctrl, Shift, or Windows key) in keypress handlers using the KeyboardDevice.Modifier property.  For example:

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if ((e.Key == Key.G) &&
                (e.KeyboardDevice.Modifiers == ModifierKeys.Control))
                MessageBox.Show("Ctrl+G detected");
        }

Note that this method doesn’t distinguish between whether you pressed the left vs. right Ctrl keys.  This is normally what you want.  If you do want to distinguish between the two, you can explicitly check for left vs. right.

        private void Window_KeyDown(object sender, KeyEventArgs e)
        {
            if ((e.Key == Key.G) &&
                (Keyboard.IsKeyDown(Key.LeftCtrl)))
                MessageBox.Show("Left Ctrl+G detected");
            else if ((e.Key == Key.G) &&
                (Keyboard.IsKeyDown(Key.RightCtrl)))
                MessageBox.Show("Right Ctrl+G detected");
        }

#1,075 – Triggering on IsKeyboardFocusWithin Property

You can set up a trigger that fires whenever a control’s IsKeyboardFocused property becomes truechanging the value of some other property when the control gains keyboard focus.

You can also trigger on the IsKeyboardFocusWithin property.  This property will get set to true for an element when any child of that element has keyboard focus.

In the example below, we set the background color of either StackPanel when any element within the StackPanel has focus.  This technique may be useful when you want to keep track of what section of a window the user is working in and do something based on that knowledge.

    <Window.Resources>
        <Style x:Key="HoneydewFocus" TargetType="StackPanel">
            <Style.Triggers>
                <Trigger Property="IsKeyboardFocusWithin" Value="true">
                    <Setter Property="Background" Value="Honeydew"/>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>
    
    <StackPanel>
        <StackPanel Orientation="Horizontal" Margin="10"
                    Style="{StaticResource HoneydewFocus}">
            <Button Content="Click Me" VerticalAlignment="Center"/>
            <TextBox Width="200" Height="25" Margin="10"/>
        </StackPanel>

        <StackPanel Orientation="Horizontal" Margin="10"
                    Style="{StaticResource HoneydewFocus}">
            <Button Content="Or Me" VerticalAlignment="Center"/>
            <TextBox Width="200" Height="25" Margin="10"/>
        </StackPanel>
    </StackPanel>

1075-001

1075-002

#1,074 – Attached Event Syntax

Attached events allow attaching a handler for an event that is defined in an element other than the one adding the handler.  For example, a StackPanel might define a handler for the Click event that is defined in ButtonBase.

When defining handlers in XAML, the event name is used by itself if that event is defined for the element raising the event.

        <Button Content="Click Me" Click="Button_Click"/>

When defining a handler on an element that does not define the handler’s event, you prefix the event name with the name of the class that defines the event.

    <StackPanel Button.Click="StackPanel_Button_Click">