Use global command bindings in WPF and C#

[global command bindings]

The example Use custom command bindings in WPF and C# explains how you can make a program use custom commands. (This is a confusing topic so read that post before you continue with this one.)

That technique doesn’t quite work if you want to use global command bindings to manage controls on multiple windows. For example, suppose your application should be able to perform some global task. The previous example shows how to use commands to manage that task on a single window, but it doesn’t work if you want to allow controls on multiple windows to participate. Fortunately it’s not too hard to modify that example so it works.

Before I show how to do that, let me explain this example a bit. When it loads, the main window creates a secondary window of type SecondaryWindow. That class defines the following public field.

public Window1 MainWindow;

The main window uses this code to create and display the secondary window.

// Display a secondary window.
Secondary = new SecondaryWindow();
Secondary.MainWindow = this;
...
Secondary.Show();

This code creates the SecondaryWindow, sets its MainWindow field to refer to the main window, and displays the window. (I’ll describe the omitted statements shortly.)

The main window defines the following public field.

// A boolean indicating whether changes are allowed.
public bool AllowChangeBackground = true;

Both windows’ Toggle Allow buttons toggle this value. For example, the secondary window’s Toggle Allow button uses this code.

private void ToggleAllow_Click(object sender, RoutedEventArgs e)
{
    MainWindow.AllowChangeBackground =
        !MainWindow.AllowChangeBackground;
}

Now let me talk about the command. The following code shows the main window’s complete Loaded event handler.

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    // Create the Ctrl+B gesture.
    InputGestureCollection change_bg_gestures =
        new InputGestureCollection();
    change_bg_gestures.Add(
        new KeyGesture(Key.B, ModifierKeys.Control, "Ctrl+B"));

    // Create the ChangeBackground command.
    RoutedUICommand change_bg_command =
        new RoutedUICommand(
            "Change the application's background color.",
            "ChangeBackground",
            typeof(Window),
            change_bg_gestures);

    // 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 ChangeBackground controls.
    btnChangeBackground.Command = change_bg_command;

    // Display a secondary window.
    Secondary = new SecondaryWindow();
    Secondary.MainWindow = this;
    Secondary.btnChangeBackground.Command = change_bg_command;
    Secondary.CommandBindings.Add(change_bg_binding);
    Secondary.Show();
}

This code creates the command more or less the same way the previous example did. It makes a gesture collection, defines the Ctrl+B gesture, and uses the collection to create the RoutedUICommand.

It then creates a CommandBinding object and associates the command with its CanExecute and Executed event handlers. The code then adds the CommandBinding to the window’s CommandBindings collection and sets the btnChangeBackground button’s Command property to the command.

Next comes the new stuff. After it creates the secondary window, the code sets that window’s btnChangeBackground button’s Command property to the same command. The line highlighted in blue then adds the binding to the secondary window’s CommandBindings collection. I you omit that step, the secondary window doesn’t receive notification when the command’s CanExecute event handler fires so it can’t update its Background button.

The rest of the example is similar to the previous one. The following code shows the command’s CanExecute and Executed event handlers.

private void change_bg_CanExecute(object sender,
    CanExecuteRoutedEventArgs e)
{
    if (!IsLoaded) return;
    e.CanExecute = AllowChangeBackground;
}

private Brush brush1 = Brushes.LightBlue;
private Brush brush2 = Brushes.LightGreen;
void change_bg_Executed(object sender, ExecutedRoutedEventArgs e)
{
    Brush brush;
    if (Background == brush2) brush = brush1;
    else brush = brush2;

    Background = brush;
    Secondary.Background = brush;
}

These event handlers are fairly straightforward. This example only attaches two buttons to the ChangeBackground command, but you can add any number of other buttons, menu items, and other controls to it.

For additional details, see the previous example and download the example.


Download Example   Follow me on Twitter   RSS feed   Donate




About RodStephens

Rod Stephens is a software consultant and author who has written more than 30 books and 250 magazine articles covering C#, Visual Basic, Visual Basic for Applications, Delphi, and Java.
This entry was posted in events, user interface and tagged , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *