Tag Archives: WPF commands

Custom commands in WPF

We’ve looked at using built-in commands and providing bindings for built-in commands, so it’s time to have a look at creating a custom command from scratch. Conventionally, a Command implements the singleton design pattern, which means that in any running program, there should be at most one instance of the Command object in existence. The rationale behind this is that a Command represents a particular set of instructions which is fixed, but which can be called from a number of different sources or actions, such as the copy command which could be called from a menu, a toolbar button or by typing Ctrl+C.  All these actions should do the same thing, so they should all refer to the same Command object.

As such, we should create a Command object as a singleton. There are various ways this can be done in code, but we’ll look at just one here: declaring the new custom Command as a static object that is created in a static constructor (which is called once when the program starts, and that’s it). We create a new class for our custom Command, and its code looks like this:

  class CustomCommands
  {
    public static RoutedUICommand AquaButtonCommand;

    static CustomCommands()
    {
      InputGestureCollection aquaButtonInputs = new InputGestureCollection();
      aquaButtonInputs.Add(new KeyGesture(Key.A, ModifierKeys.Alt));
      aquaButtonInputs.Add(new MouseGesture(MouseAction.WheelClick, ModifierKeys.Control));
      AquaButtonCommand = new RoutedUICommand("Aqua", "AquaButton", typeof(CustomCommands), aquaButtonInputs);
    }
  }

The RoutedUICommand class is the WPF class for creating a routed command connected to a user interface object. Remember that a routed command follows the same routing rules as an ordinary event: starting at the root of the interface tree (typically the Window), each event first tunnels through the tree until it reaches the control that generated the event, and then bubbles back up the tree, visiting each control in the tree along the way in both directions. A ‘preview’ handler for the event can be placed at any point on the path, and it will be fired as the Command tunnels down from the root; a regular handler will be fired as the Command bubbles back up to the root.

We’ve called the custom Command AquaButtonCommand, since it has the frivolous effect of changing part of the UI to the colour aqua. This seemed a slighly more picturesque way of illustrating where the events were handled than the usual method of printing a message to the console.

This example shows how to attach a KeyGesture and a MouseGesture to the Command. (We’ll attach the Command to the ‘Aqua’ button later.) The code here causes the Command to be executed when the Alt+A key combination is pressed, or when the Ctrl key is held down and the mouse wheel rotated (somewhat confusingly, the WheelClick mouse action isn’t a press of the wheel; it’s a rotation of the wheel).

In the RoutedUICommand constructor call on the last line, the first argument is a string that can be used elsewhere as a description of the command (for example, as text on a Button). The second argument is a string that is used in the internal representation of the Command (as in serialization). The third argument is the data type of the enclosing class, and the last argument is the InputGestureCollection we’ve just created.

So much for creating the custom command. Once you have the new command, it can be used in the same way as any of the built-in commands, so there are no surprises here. However, one thing we haven’t yet considered is how to enable and disable a command from within the code.

In our first example, where we attached cut, copy and paste commands to a TextBox, the TextBox did all the work of deciding when a command was enabled or disabled. If there was some text on the clipboard, the paste command was enabled; if some text was selected in the TextBox, cut and copy were enabled and so on. Most commands don’t have this functionality built in so it’s up to the programmer to decide when to enable and disable a command.

We’ll attach our custom AquaButtonCommand to the Button labelled ‘Aqua’, and then do a few other things with the command. The code looks like this:

      customButton.Command = CustomCommands.AquaButtonCommand;
      customButton.Content = CustomCommands.AquaButtonCommand.Text;
      CommandBinding customBinding = new CommandBinding(CustomCommands.AquaButtonCommand);
      customBinding.CanExecute += new CanExecuteRoutedEventHandler(aquaBinding_CanExecute);
      customBinding.Executed += new ExecutedRoutedEventHandler(aquaBinding_Executed);
      CommandBindings.Add(customBinding);
      //customButton.CommandBindings.Add(customBinding);

On line 1, we attach the command to the button. On line 2, we use the descriptive text we specified when creating the command as the label for the Button. Line 3 creates a binding for the command in the usual way. We’ll look at line 4 in a minute. Line 5 specifies a handler for the Executed event, and line 6 attaches the binding to the Window object containing the whole UI. Line 7 is commented out for now.

The handler looks like this:

    void aquaBinding_Executed(object sender, ExecutedRoutedEventArgs e)
    {
      if (sender == customButton)
      {
        ((Button)sender).Background = new SolidColorBrush(Colors.Aqua);
      }
      else if (sender == this)
      {
        ((Window)sender).Background = new SolidColorBrush(Colors.Aqua);
      }
    }

The handler attempts to discover what the sender of the event is (either the Aqua button or the underlying window) and then sets the background colour of the sender to Aqua.

Now back to the CanExecute event, for which we specified a handler above. The handler looks like this:

    void aquaBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
    {
      // WriteLine for testing when CanExecute is called...
      Console.WriteLine("aquaBinding_CanExecute");

      // Custom button becomes enabled when text is correct
      if (textBox1.Text.Equals("Enable"))
      {
        e.CanExecute = true;
      }
    }

The CanExecute event is generated whenever there is any interaction with any part of the UI. By default, if no handler is specified for this event, CanExecute is ‘true’, so the Aqua button would be enabled. However, as soon as we attach a handler for the event, the default value is ‘false’, so the Aqua button starts off disabled here.

Since it’s difficult to know when the event happens, we’ve written a WriteLine() statement that prints a message each time the handler is called. If you run the project as a console application, you’ll see this message printed every time you click anywhere in the window with the mouse, or any time you type on the keyboard. The handler basically gives you the chance to enable or disable its associated command in response to any interaction with the program. To illustrate this, we enable the command whenever textBox1 contains the text “Enable”. If you start up the program, you’ll note that the Aqua button starts off disabled. If you delete the existing text in textBox1 and then type Enable, you’ll see the button become enabled after you type in the last letter “e”. At this point, the keyboard and mouse shortcuts also kick in, and you can run the command either by pressing the Aqua button, typing Alt+A, or Ctrl+MouseWheel. Since the handler was attached to the Window, it is the Window’s background (visible as the unsightly gap between the two TextBoxes) that turns aqua.

If we now disconnect the binding from the Window and attach it to customButton instead (comment out line 6 and uncomment line 7 in the code dealing with the binding above), then the command can be fired only if the button is pressed directly or else it has the keyboard focus (you can tab through the controls until it gets the focus). Pressing the button now causes the button’s background to become aqua, rather than the Window’s, since the button is now the sender of the command. (Curiously, when the button has focus, the Alt+A key combination will fire the command, but the Ctrl+MouseWheel gesture won’t. Not sure why…)

If you attach the binding to both the Window and the button, then the sender of the command is the Window if the button doesn’t have focus, and the button if it does have focus, as you might expect.

Code available here.

Advertisements

Commands in WPF

In addition to standard event handling, WPF offers a specialized type of handler called a Command. There’s some debate about how useful the Command is, compared to the ordinary event handler, but they do offer some nice features so they are worth a mention.

There are a number of commands that appear in many applications, and WPF’s Command classes provide ready-made versions of a number (144 to be exact) of them. Some of the most common Commands are those associated with text editing, such as copy, cut and paste. We’ll begin with a little application that illustrates how these actions can be handled using Commands.

Create a new project in Expression Blend or Visual Studio, and create a layout similar to that shown:

This layout is built on a DockPanel, with a Menu and its associated MenuItems docked to the top, a ToolbarTray and its Buttons docked to the left, and two TextBoxes docked to the bottom. The ugly gap between the two Textboxes is there for a reason, as we’ll see shortly.

The Edit menu contains the 3 edit commands: cut, copy and paste. Obviously we’d like each of these menu items to do the same thing as the corresponding button in the toolbar. We could just create an event handler for, say, the Copy button and then point the menu item at the same handler. However, WPF’s ApplicationCommands class contains these 3 (and quite a few other) commands ready-made. We’ll have a look at how you can use these commands out of the box first, before looking in a bit more depth at how they work, and how you can create your own command.

You can attach a Command to a UI object either by editing the XAML or the C# code. In XAML, you can edit the Button entries to look like this:

				<Button x:Name="cutButton" Content="Cut" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="75" Command="ApplicationCommands.Cut"/>
				<Button x:Name="copyButton" Content="Copy" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="75" Command="ApplicationCommands.Copy"/>
				<Button x:Name="pasteButton" Content="Paste" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="75" Command="ApplicationCommands.Paste"/>

You can add similar Command labels to the corresponding MenuItems in XAML as well.

In C#, you can insert a line such as this for cutButton:

cutButton.Command = ApplicationCommands.Cut;

If you run the program at this point (you should download and run the program if you aren’t building it yourself), you’ll discover that you can select text in either textbox and use either the toolbar buttons or the MenuItems to cut, copy and paste the text. You should also notice that if no text is selected in either textbox, the Cut and Copy Buttons and MenuItems are disabled. The Buttons and MenuItems are also able to tell which textbox to apply their operations to, as it is the textbox that had the keyboard focus before the Button or MenuItem was selected.

This semi-magical behaviour is due to the way a TextBox is designed. In order to understand why things Just Work with the cut, copy and paste buttons, and also how to deal with other Commands and even define your own, we need to delve a bit more deeply into what’s going on underneath. We’ll do that in the next post.

Code available here (ignore everything except the cut, copy and paste buttons and menu items for now).

Commands, targets and bindings

In the last post, we saw how to use some built-in WPF Commands to implement behaviour such as cut, copy and paste in TextBoxes. In that example, most of the functionality is already coded into the TextBox control for us, so we had very little work to do. To use Commands in any more complex situation, we need to understand a bit more about how they work.

There are four main components needed in the implementation of a Command. First, there is the Command itself. A Command object contains some basic information to be associated with the command that it will ultimately run, such as any input gestures (keyboard shortcuts or mouse actions, usually) associated with the Command. All the 144 built-in Commands provided by WPF are objects of this type. Some, such as copy, have some input gestures (Control+C for copy) pre-defined, while others do not. For now, we’ll consider only these given Command objects, and consider custom-made Commands later on.

Second, a Command needs a source, which is the object that generates the command. A command source is usually some UI element such as a Button or MenuItem. For example, a Button can be pressed to initiate a copy action.

Third, we need a target, which is an object on which the Command will act. In the case of the copy action, the target must be some control that contains something we can copy, such as text in a TextBox.

Finally, the guts of a Command are contained in a CommandBinding. A CommandBinding contains the event handlers that are called when the command is run, or when we need to check if a command is able to be run. Each UI control has a collection of CommandBindings, so that more than one Command can be associated with a given control. Conversely, we can also associate one Command with more than one control (as with the copy command being associated with both a toolbar button and a menu item).

Here’s a reminder of the interface we used in the last post:

Returning to our simple example from the last post, we saw there that all we did was attach a Command object to each Button and MenuItem. We didn’t specify any command targets or command bindings, so how did the program know what to do?

The answer comes in two parts. First, if no target is specified for a Command, the control that last had the keyboard focus before the Command was invoked is taken as the target. To see this, select some text (e.g. from Notepad) into the clipboard before starting up the program. When the program starts, none of its controls has the keyboard focus and you’ll see that the Paste button and menu item are disabled, even though there is something on the clipboard that could be pasted. When you click in either TextBox, the Paste button becomes enabled, since that TextBox has now become the Command target for the Paste command.

The CommandBindings for paste, cut and copy are pre-written when the target is a TextBox, so we don’t need to worry about them. With other Commands, things aren’t quite so simple.

To see how the other bits of a Command work, we’ll do some experiments with the Find button. Although the Find command is one of WPF’s built-in Commands, it doesn’t have pre-written bindings, so we need to do some work ourselves. For simplicity, we’ll work entirely in the C# code file. In the MainWindow() constructor, we’ll add the following at the end:

      findButton.Command = ApplicationCommands.Find;
      //findButton.CommandTarget = textBox1;
      CommandBinding binding = new CommandBinding(ApplicationCommands.Find);
      binding.Executed += new ExecutedRoutedEventHandler(binding_Executed);
      //findButton.CommandBindings.Add(binding);
      //textBox1.CommandBindings.Add(binding);

We’ve assigned the Find command to findButton. Ignoring the commented lines (we’ll use them later), we next create a CommandBinding associated with Find. We then provide a handler for the Executed event, which is run when the command is executed. For now, we don’t add this binding to any control, so it isn’t actually used yet.

The handler looks like this:

    void binding_Executed(object sender, ExecutedRoutedEventArgs e)
    {
      MessageBox.Show("Find dialog");
    }

All it does is display a MessageBox.

Now, according to what we’ve just said, since we haven’t specified a command target for Find, it should use whatever has the keyboard focus when findButton is pressed. If you run the program and select a TextBox, you’ll see that Find remains disabled. Why does this happen? After all, with Paste, the button became enabled as soon as we selected a TextBox.

The reason is that a TextBox has no built-in binding for Find, so even though the selected TextBox is being used as the command target, the lack of a binding means there are no instructions for Find to follow when it is invoked on the TextBox, so nothing can happen. As a result, the program won’t let you do anything that would try to invoke Find, and the button is disabled.

Next, try uncommenting the line:

textBox1.CommandBindings.Add(binding);

Now when we run the program, Find is disabled initially, but if we click in textBox1, it becomes enabled, and clicking on it brings up the MessageBox. However, it is only this TextBox that enables Find: clicking in textBox2 disables it again. This is because it is only textBox1 that has a binding for Find, so only it knows what to do when Find is invoked.

Next, try commenting out this line again, and uncommenting the binding to findButton, so the last two lines above become:

      findButton.CommandBindings.Add(binding);
      //textBox1.CommandBindings.Add(binding);

Now we find the Find button is enabled right from the start; we don’t need to click in either TextBox. This is because the Find button itself now knows how to handle the Find command, so it doesn’t need to rely on an implicit target in the form of a TextBox having the keyboard focus. In effect, findButton becomes its own target.

WPF is actually quite intelligent in being able to figure out when a control can handle a Command. If you now comment out the line beginning binding.Executed, for example, so that no handler is specified for the Executed event, the Find button will again be disabled even though a CommandBinding has been attached to findButton.

For our final experiment, use the following comment pattern in the above code:

      findButton.Command = ApplicationCommands.Find;
      findButton.CommandTarget = textBox1;
      CommandBinding binding = new CommandBinding(ApplicationCommands.Find);
      binding.Executed += new ExecutedRoutedEventHandler(binding_Executed);
      findButton.CommandBindings.Add(binding);
      //textBox1.CommandBindings.Add(binding);

We’ve now specified the target of findButton to be textBox1, but we’ve attached the binding to findButton. Now nothing you do can enable the Find button, since its target doesn’t know how to handle the Find command. Uncommenting the last line as follows again enables the Find button right from the start:

      findButton.Command = ApplicationCommands.Find;
      findButton.CommandTarget = textBox1;
      CommandBinding binding = new CommandBinding(ApplicationCommands.Find);
      binding.Executed += new ExecutedRoutedEventHandler(binding_Executed);
      //findButton.CommandBindings.Add(binding);
      textBox1.CommandBindings.Add(binding);

This might surprise you, since you might think that you’d need to give textBox1 the keyboard focus in order to enable the Find button. However, what has happened is that an explicit target has been given, and that target has a binding for the Find command attached, so the button is enabled at all times. It is only when no target has been set explicitly that the keyboard focus is used to select which target applies.

As you can see, knowing when a Command is enabled can be a bit tricky. Things get even worse when we consider enabling and disabling commands in the code, but we’ll look at that in the next post.

Code for this post is available here (but ignore the bits on custom commands, which will be covered later).