Title: Use custom command bindings in WPF and C#
The example Use pre-defined command bindings in WPF and C# explains how you can make a program use pre-defined commands. (This is a confusing topic so read that post before you continue with this one.)
This example shows how you can make your own command objects to use when the pre-defined ApplicationCommands objects don't do what you need them to do. For instance, this example defines an Execute command.
The steps for making a custom command are basically the same as those for using a pre-defined command. You need to:
- Create a command object.
- Associate the object with its CanExecute and Executed event handlers.
- Define the CanExecute and Executed event handlers.
- Associate the buttons, menu items, and other user interface elements with the commands by setting their Command properties in XAML code.
The difference is that you need to make the command object in your code instead of using one of the pre-defined ApplicationCommands objects.
There are two main ways you can do this. First you can create a generic RoutedUICommand object to represent the command. Second you can create a static (shared) object to represent the command. The techniques are roughly the same. They just differ in where the command object is created.
This example demonstrates both approaches. First its Window_Loaded event handler uses the following code to prepare the ChangeForeground command.
// Create the Ctrl+F gesture.
InputGestureCollection change_fg_gestures =
new InputGestureCollection();
change_fg_gestures.Add(
new KeyGesture(Key.F, ModifierKeys.Control, "Ctrl+F"));
// Create the ChangeForeground command.
RoutedUICommand change_fg_command =
new RoutedUICommand(
"Change the application's foreground color.",
"ChangeForeground",
typeof(Window1),
change_fg_gestures);
// Bind the ChangeForeground command to its event handlers
CommandBinding change_fg_binding =
new CommandBinding(change_fg_command);
change_fg_binding.CanExecute += change_fg_CanExecute;
change_fg_binding.Executed += change_fg_Executed;
this.CommandBindings.Add(change_fg_binding);
// Set Command properties for ChangeForeground controls.
mnuChangeForeground.Command = change_fg_command;
btnChangeForeground.Command = change_fg_command;
btnForeground.Command = change_fg_command;
The code fiirst creates an InputGestureCollection and defines the Ctrl+F gesture. It then creates a new RoutedUICommand object to represent the ChangeForeground command. It passes the InputGestureCollection into the constructor so the gesture activates this command.
Next the code creates a CommandBinding for the command and binds it to the command's CanExecute and Executed event handlers. It then adds the binding to the window's CommandBindings collection.
The code finishes by setting the Command property for the button's and menu item that should activate the command to the RoutedUICommand object.
Now the ChangeForeground command works like the commands defined in the previous example. When you use the check box to enable or disable the command, the buttons and menu item are automatically enabled or disabled.
Note that the menu item automatically displays the input gesture Ctrl+F. This is automatic because the command knows about that input gesture and the menu item knows that it should display the shortcut.
For the second approach the program uses the following MyCommands class.
public static class MyCommands
{
// The command objects.
private static RoutedUICommand changeBackground;
// Propetry to get the command objects.
public static RoutedUICommand ChangeBackground
{ get { return changeBackground; } }
// Constructor.
static MyCommands()
{
// Create the Ctrl+B gesture.
InputGestureCollection change_bg_gestures =
new InputGestureCollection();
change_bg_gestures.Add(
new KeyGesture(Key.B, ModifierKeys.Control, "Ctrl+B"));
// Make the ChangeBackground command object
// giving it the Ctrl+B gesture.
changeBackground = new RoutedUICommand(
"Change the application's background color",
"ChangeBackground",
typeof(MyCommands), change_bg_gestures);
}
}
The class begins by declaring a private RoutedUICommand object and a public read-only ChangeBackground property to return that object.
The class's constructor (which is called automatically because this is a static class) creates an InputGestureCollection and defines the Ctrl+B gesture. It then creates the RoutedUICommand object, passing its constructor the gesture collection.
This takes care of some of the steps performed by the code for the ChangeForeground command. The following code in the Window_Loaded event handler finishes setting up the command.
// Create the ChangeBackground command.
RoutedUICommand change_bg_command = MyCommands.ChangeBackground;
// Bind the ChangeBackground command to its event handlers
CommandBinding change_bg_binding =
new CommandBinding(change_bg_command);
change_bg_binding.CanExecute += change_bg_CanExecute;
change_bg_binding.Executed += change_bg_Executed;
this.CommandBindings.Add(change_bg_binding);
// Set Command properties for Execute controls.
mnuChangeBackground.Command = change_bg_command;
btnChangeBackground.Command = change_bg_command;
btnBackground.Command = change_bg_command;
This code starts by getting the ChangeBackground command by using the MyCommands class's ChangeBackground property. It then creates the command's binding and connects it to its CanExecute and Executed event handlers. Finally it sets the Command properties for the command's buttons and menu item as before.
This approach makes creating the command a tiny bit simpler for the main program. It also follows Microsoft's practice for the pre-defined commands more closely.
Download the example to experiment with it and to see additional details.
|