#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;
        }
Advertisement

#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

#344 – The CommandBinding CanExecute Event Determines Whether a Button is Enabled

When you associate a button’s Command property with a CommandBinding object,and bind the CommandBinding object to both Executed and CanExecute handlers, the Button control will automatically toggle between enabled/disabled, depending on the code in the CanExecute method.

Suppose we create two buttons, binding them to open/close commands.

    <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
        <Button Content="Open" Command="ApplicationCommands.Open"
                VerticalAlignment="Center" Padding="10,5" Margin="5"/>
        <Button Content="Close" Command="ApplicationCommands.Close"
                VerticalAlignment="Center" Padding="10,5" Margin="5"/>
    </StackPanel>

Then we create a CommandBinding and associated handlers.

		public MainWindow()
		{
			this.InitializeComponent();

            CommandBindings.Add(new CommandBinding(ApplicationCommands.Open, Open_Executed, Open_CanExecute));
            CommandBindings.Add(new CommandBinding(ApplicationCommands.Close, Close_Executed, Close_CanExecute));
        }

        private bool isOpen = false;

        public void Open_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("Open");
            isOpen = true;
        }

        public void Open_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = !isOpen;
        }

        public void Close_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("Close");
            isOpen = false;
        }

        public void Close_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = isOpen;
        }

The buttons will now automatically be enabled/disabled, depending on the value of isOpen.

#343 – Associating Multiple Controls with the Same Command

One benefit of using commands in WPF, as opposed to writing event handlers, is that it’s easier to link multiple controls to a single command.  With commands, you can create a single command object, bind it to a method, and then associate the command with more than one control by setting the Command property of each control.

In the example below, we associate the ApplicationCommands.Open command with both a Button and a MenuItem.

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

    <StackPanel>
        <Button Content="Open" Command="ApplicationCommands.Open" HorizontalAlignment="Center" />
    </StackPanel>

In the code-behind, we still only have to create a single CommandBinding instance.

		public MainWindow()
		{
			this.InitializeComponent();

            CommandBindings.Add(new CommandBinding(ApplicationCommands.Open, Open_Executed, Open_CanExecute));
        }

        public void Open_Executed(object sender, ExecutedRoutedEventArgs e)
        {
            MessageBox.Show("Open file code goes here");
        }

        public void Open_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
            e.CanExecute = true;   // Can we open file?
        }