Skip to main content

C# WPF Tutorial - Command Bindings and Custom Commands [Intermediate]


So a few weeks ago, we posted a tutorial on using the built incommands in WPF. Well, today we are going to take a look at the other side of that - creating and using your own custom command and command bindings. First we will take a look at setting up our own bindings to existing commands, and then we will see how to create our own commands from scratch.

So an important thing to know, in order for command binding to make sense, is that (like many things in WPF) commands bubble. So when a command is triggered, it bubbles up along the WPF element tree from its origin (the command target, which we talked about in the previous tutorial), looking for an element that recognizes and can handle the command. The way that you can set up an element to handle a command is by creating a command binding. This can be done in either XAML or the code behind code - and we are going to take a look at the XAML first.
<Window x:Class="CustomCommandTest.CommandWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Custom Command Test" Height="300" Width="300">

  <Window.CommandBindings>
    <CommandBinding Command="Help" 
        CanExecute="HelpCanExecute"
        Executed="HelpExecuted" />
  </Window.CommandBindings>

  <Button Command="Help" Content="Help Command Button" />
</Window>
 
So here we have a pretty sad little window (all it has is a single button). That button, when pressed, will cause the built in Help command to be executed. Now, without any command bindings, that command would just bubble up till it couldn't bubble up anymore, and just disappear. But in this case, we added a command binding to the window. This command binding listens for the Help command, and uses the HelpCanExecute method to determine if the command can execute, and the HelpExecute method to actually do the execution. These two methods exist in the code behind for the window and look like this:
private void HelpCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
  e.CanExecute = true;
  e.Handled = true;
}

private void HelpExecuted(object sender, ExecutedRoutedEventArgs e)
{
  MessageBox.Show("Hey, I'm some help.");
  e.Handled = true;
}
 
The HelpCanExecute method is used to determine if the Help command is enabled or disabled. Here, we have it enabled, by setting the CanExecute property on the CanExecuteRoutedEventArgs to true. If we had disabled it, anything linked to this command (like that button) would automatically become disabled. The second line in that method sets the Handled property on the event args to true - this lets the system know that this command binding has handled this command, and that it doesn't need to bubble farther up the UI element chain.

The HelpExecuted is what actually gets run when the command is executed, and in this case all we do is show a message box. And of course, we set the handled flag to true. Now, it is true that setting handled to true is not needed here or in the HelpCanExecute (because there are no other command bindings in this application, and there are no other elements to bubble up to), but it is probably good practice.

Another interesting thing you can do with commands is hook input gestures up to them. Take a look at the following XAML:
<Window x:Class="CustomCommandTest.CommandWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Custom Command Test" Height="300" Width="300">

  <Window.CommandBindings>
    <CommandBinding Command="Help" 
        CanExecute="HelpCanExecute"
        Executed="HelpExecuted" />
  </Window.CommandBindings>

  <Window.InputBindings>
    <KeyBinding Command="Help" Key="H" Modifiers="Ctrl"/>
    <MouseBinding Command="Help" MouseAction="LeftDoubleClick" />
  </Window.InputBindings>

  <Button Command="Help" Content="Help Command Button" />
</Window>
 
With this XAML, we have added some imput gestures that will also trigger the command. Now, if the window has focus, and you hit Ctrl+H or double click anywhere, the help command get executed. This makes it really easy to hook up common keyboard shortcuts. Need ctrl+s to save? You just have to hook up a KeyBinding to call the right command.

OK, now onto creating your own custom commands. There really isn't that much to it, so while we are at it, let's take a look at how to hook up things like command bindings and input gestures in code:
<Window x:Class="CustomCommandTest.CommandWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Custom Command Test" Height="300" Width="300">

  <Window.CommandBindings>
    <CommandBinding Command="Help" 
        CanExecute="HelpCanExecute"
        Executed="HelpExecuted" />
  </Window.CommandBindings>

  <Window.InputBindings>
    <KeyBinding Command="Help" Key="H" Modifiers="Ctrl"/>
    <MouseBinding Command="Help" MouseAction="LeftDoubleClick" />
  </Window.InputBindings>

  <StackPanel>
    <Button Command="Help" Content="Help Command Button" />
    <Button Content="My Command" x:Name="MyCommandButton" />
  </StackPanel>
</Window>

public partial class CommandWindow : Window
{
  public static RoutedCommand MyCommand = new RoutedCommand();

  private bool _helpCanExecute = true;

  public CommandWindow()
  {
    InitializeComponent();

    CommandBinding cb = new CommandBinding(MyCommand, 
        MyCommandExecute, MyCommandCanExecute);
    this.CommandBindings.Add(cb);

    MyCommandButton.Command = MyCommand;

    KeyGesture kg = new KeyGesture(Key.M, ModifierKeys.Control);
    InputBinding ib = new InputBinding(MyCommand, kg);
    this.InputBindings.Add(ib);
  }

  private void HelpCanExecute(object sender, CanExecuteRoutedEventArgs e)
  {
    e.CanExecute = _helpCanExecute;
    e.Handled = true;
  }

  private void HelpExecuted(object sender, ExecutedRoutedEventArgs e)
  {
    MessageBox.Show("Hey, I'm some help.");
  }

  private void MyCommandCanExecute(object sender, CanExecuteRoutedEventArgs e)
  {
    e.CanExecute = true;
  }

  private void MyCommandExecute(object sender, ExecutedRoutedEventArgs e)
  {
    MessageBox.Show("My Command!");
    _helpCanExecute = !_helpCanExecute;
  }
 
Ok, so we have a bunch of new stuff here. The XAML is almost identical (the only new thing is the addition of a new button, and surrounding the two buttons with a StackPanel). So I think we can skip right to the top of the C# code - the RoutedCommand. This is how you create a new command - you create a new static RoutedCommand. Thats it. There really is nothing else to it, since it is just sort of a connector piece - the real meat is whatever you put in the execute and can execute methods of the binding.

Now to bind that command to the window. Since we already know how to do it in XAML, we did it in code here. You have to create a new CommandBinding instance, which takes the command and the execute/can execute methods. Once you have that, you just add it to the CommandBindings collection on whatever UI element you want the binding to be on - in this case, the window. And your all set!

Ah, but we still need something to actually trigger the command, and this is where we use that new extra button in XAML named MyCommandButton. This time we are setting the command property of the button in C# code, and as you can tell, it is just as easy as it was in XAML. All we do is set it to MyCommand and now when that button is pressed, the MyCommandExecute method will get run.

Adding input gestures in code is just as easy. First, you create a Gesture - and in our case we made a KeyGesture for the gesture Ctrl+M. Then you take that gesture and make a new InputBinding - and the input binding also takes the command you are binding to. Finally, you add that new input binding to the InputBindings collection on whatever element you want (in this case the window again).

Just as a random note, when you no longer want the binding to be active, all you have to do is remove it from the collection that you added it to (which is really easy since both the InputBindings and CommandBindings have your standard collection manipulation methods.

Oh, and there is one last fun thing in the code above. As you probably noticed, the execution of MyCommand will actually change the Can Execute state of the Help command that we put together earlier. So as you click on the MyCommandButton, the help button will toggle between enabled and disabled states, as the _helpCanExecute variable changes.

I hope you enjoyed this intro to the fun world of WPF commands. While these examples here are kind of silly, this disassociation of the executor and the actual execution logic come in quite handy as programs get larger, especially once you take into account what can be done with bubbling commands.

Comments

Popular posts from this blog

C# Snippet - Shuffling a Dictionary [Beginner]

Randomizing something can be a daunting task, especially with all the algorithms out there. However, sometimes you just need to shuffle things up, in a simple, yet effective manner. Today we are going to take a quick look at an easy and simple way to randomize a dictionary, which is most likely something that you may be using in a complex application. The tricky thing about ordering dictionaries is that...well they are not ordered to begin with. Typically they are a chaotic collection of key/value pairs. There is no first element or last element, just elements. This is why it is a little tricky to randomize them. Before we get started, we need to build a quick dictionary. For this tutorial, we will be doing an extremely simple string/int dictionary, but rest assured the steps we take can be used for any kind of dictionary you can come up with, no matter what object types you use. Dictionary < String , int > origin = new Dictionary < string , int >(); ...

C# WPF Printing Part 2 - Pagination [Intermediate]

About two weeks ago, we had a tutorial here at SOTC on the basics of printing in WPF . It covered the standard stuff, like popping the print dialog, and what you needed to do to print visuals (both created in XAML and on the fly). But really, that's barely scratching the surface - any decent printing system in pretty much any application needs to be able to do a lot more than that. So today, we are going to take one more baby step forward into the world of printing - we are going to take a look at pagination. The main class that we will need to do pagination is the DocumentPaginator . I mentioned this class very briefly in the previous tutorial, but only in the context of the printing methods on PrintDialog , PrintVisual (which we focused on last time) and PrintDocument (which we will be focusing on today). This PrintDocument function takes a DocumentPaginator to print - and this is why we need to create one. Unfortunately, making a DocumentPaginator is not as easy as...

C# WPF Tutorial - Implementing IScrollInfo [Advanced]

The ScrollViewer in WPF is pretty handy (and quite flexible) - especially when compared to what you had to work with in WinForms ( ScrollableControl ). 98% of the time, I can make the ScrollViewer do what I need it to for the given situation. Those other 2 percent, though, can get kind of hairy. Fortunately, WPF provides the IScrollInfo interface - which is what we will be talking about today. So what is IScrollInfo ? Well, it is a way to take over the logic behind scrolling, while still maintaining the look and feel of the standard ScrollViewer . Now, first off, why in the world would we want to do that? To answer that question, I'm going to take a an example from a tutorial that is over a year old now - Creating a Custom Panel Control . In that tutorial, we created our own custom WPF panel (that animated!). One of the issues with that panel though (and the WPF WrapPanel in general) is that you have to disable the horizontal scrollbar if you put the panel in a ScrollV...