Tuesday 19 February 2013

Handling shortcuts in WPF application

This is a sketchy post, to be completed or discarded later on. The objectives was having inheritance and minimizing the instantiation code.

This is the base class.


public class KeyShortcutBase
{
    private readonly RoutedCommand _command;

    private readonly CommandBinding _commandBinding;

    protected KeyShortcutBase()
    {
        this._command = new RoutedCommand();

        this._commandBinding = new CommandBinding(
            this._command,
            OnExecuted,
            OnCanExecute);
    }

    public void ConnectShortcut(
        UIElement host, InputGesture gesture)
    {
        this.ConnectShortcut(host, new[] { gesture });
    }

    public void ConnectShortcut(
        UIElement host, IEnumerable<InputGesture> gestures)
    {
        foreach (var gesture in gestures)
        {
            this._command.InputGestures.Add(gesture);
        }

        if (host != null)
        {
            host.CommandBindings.Add(this._commandBinding);
        }
    }

    protected virtual void OnCanExecute(
        object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = false;
    }

    protected virtual void OnExecuted(
        object sender, ExecutedRoutedEventArgs e)
    {
    }
}

This is an extension class allowing shorter calls.

public static class KeyShortcutExtender
{
    public static void ConnectShortcut(
        this UIElement host, 
        KeyShortcutBase shortcut, 
        IEnumerable<InputGesture> gestures)
    {
        shortcut.ConnectShortcut(host, gestures);
    }

    public static void ConnectShortcut(
        this UIElement host, 
        KeyShortcutBase shortcut, 
        InputGesture gesture)
    {
        shortcut.ConnectShortcut(host, gesture);
    }
}

This is a subclass.

public class FindItemShortcut : KeyShortcutBase
{
    protected override void OnCanExecute(
        object sender,
        CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = true;
    }

    protected override void OnExecuted(
        object sender,
        ExecutedRoutedEventArgs e)
    {
        MessageBox.Show(this.GetType().ToString());
    }
}

The subclass is instantiated in WPF Window with a single shortcut.

this.ConnectShortcut(
    new FindItemShortcut(), 
    new KeyGesture(Key.F, (ModifierKeys)6));

... and with multiple shortcuts.

this.ConnectShortcut(
    new FindItemShortcut(), 
    new InputGesture[]
        {
            new KeyGesture(Key.F, (ModifierKeys)6), 
            new KeyGesture(Key.S, ModifierKeys.Control), 
            new MouseGesture(MouseAction.RightDoubleClick)
        });

So far so good...


No comments:

Post a Comment