Alex Rivera | Logout

Keybinding a RelayCommand

Asked 2009-06-21T13:58:49.173
27

I'm using the RelayCommand in my app. It's great for putting the code in the viewmodel, but how do I bind keystrokes to my command?

RoutedUICommand has its InputGestures property, which makes the command automatically be invoked when I press the keystroke. (As an added bonus, it even makes the keystroke display in the MenuItem.) Unfortunately, there's no reusable interface for RoutedUICommand's extra properties, so I can't make a RelayUICommand that gets the same magic.

I've already tried using InputBindings:

<Window.InputBindings>
    <KeyBinding Key="PageUp" Command="{Binding SelectPreviousLayerCommand}"/>
</Window.InputBindings>

But that gets me a runtime exception, because KeyBinding.Command isn't a dependency property. (Actually, what it complains about is that KeyBinding isn't even a DependencyObject.) And since my RelayCommand is a property on my ViewModel (as opposed to the static field that RoutedUICommand is designed for), databinding is the only way I know of to reference it from XAML.

How have you guys solved this? What's the best way to bind a keystroke to a RelayCommand?

Edit
Report

1 Answer

10

You could subclass KeyBinding, add a CommandBinding dependency property that sets the Command property, and then add it to XAML like any other input binding.

public class RelayKeyBinding : KeyBinding
{
    public static readonly DependencyProperty CommandBindingProperty =
        DependencyProperty.Register("CommandBinding", typeof(ICommand), 
        typeof(RelayKeyBinding),
        new FrameworkPropertyMetadata(OnCommandBindingChanged));
    public ICommand CommandBinding
    {
        get { return (ICommand)GetValue(CommandBindingProperty); }
        set { SetValue(CommandBindingProperty, value); }
    }

    private static void OnCommandBindingChanged(
        DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var keyBinding = (RelayKeyBinding)d;
        keyBinding.Command = (ICommand)e.NewValue;
    }
}

XAML:

<Window.InputBindings>
    <RelayKeyBinding 
        Key="PageUp" 
        CommandBinding="{Binding SelectPreviousLayerCommand}" />
</Window.InputBindings>
answered 2009-09-28T23:45:03.607

Your Answer