MoonKnight
MoonKnight

Reputation: 23833

InputBinding for Windows Forms

I have an existing WPF application in which I have a fairly advanced command system. I am now developing a WinForms application in which I want to adopt a similar command system. This is going well but I am struggling with shortcuts and the key binding translation.

For the WPF case, I bind key gestures for commands to user interface elements via the following method

public void BindKeyGestures(UIElement uiElement)
{
    foreach (var keyboardShortcut in _keyboardShortcuts)
    {
        if (keyboardShortcut.KeyGesture != null)
        {
            uiElement.InputBindings.Add(new InputBinding(
                _commandService.GetTargetableCommand(_commandService.GetCommand(keyboardShortcut.CommandDefinition)),
                keyboardShortcut.KeyGesture));
        }
    }
}

Is there a way to add InputBindings for a WinForms Control (I believe this is unlikely as it is a WPF construct), and if there isn't, how can I add the shortcut without having to explicitly override ProcessCmdKey of the containing form?

Upvotes: 0

Views: 361

Answers (1)

tzachs
tzachs

Reputation: 5019

There are a few specific controls (toolstrip items, menu items) which have a ShortcutKeys property that you can use (for example: https://msdn.microsoft.com/en-us/library/system.windows.forms.toolstripmenuitem.shortcutkeys(v=vs.110).aspx).

For other controls, there's nothing built in that I know of, and you'll need to create some system yourself. Here's a simple extension method that you can use:

    public static void Bind(this Control control, Keys shortcut, Action action)
    {
        Form form = control.FindForm();
        if (form == null) throw new NullReferenceException($"Form not found for control: {control.Text ?? control.ToString()}");
        form.KeyPreview = true;
        form.KeyDown += (sender, args) =>
        {
            if (args.KeyData == shortcut) action();
        };
    }

This needs to be called after the control is assigned to a form, otherwise it would throw an exception. Also this does not cover unsubscribing the KeyDown event, which will be less trivial to implement (something along the lines of caching the control+shortcut+delegate triplets, and then unsubscribing when calling Unbind).

The above code can be used like this:

Button button = new Button { Text = "Click Me!" };
form.Controls.Add(button);
....
button.Bind(Keys.F | Keys.Control, () => doSomething()); //Will do something on Ctrl+F

Upvotes: 1

Related Questions