39

I have a WPF app that is using the MVVM pattern. Hooking up buttons to the VM is pretty straight forward since they implement the ICommand. I have a context menu that works similar. The next step is to create shortcut keys for the context menu. I can't figure out how to get the shortcut key invoke the Command. Here is an example:

<MenuItem Header="Update" Command="{Binding btnUpdate}" >
    <MenuItem.Icon>
        <Image Source="/Images/Update.png"
               Width="16"
               Height="16" />
        </MenuItem.Icon>
    </MenuItem>

now I've added this:

<Window.InputBindings>
    <KeyBinding Key="U"
                Modifiers="Control" 
                Command="{Binding btnUpdate}" />
</Window.InputBindings>

to try and connect the shortcut keys to the same binding, but this doesn't work. The error is:

Error 169 A 'Binding' cannot be set on the 'Command' property of type 'KeyBinding'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject.

Isn't there a way to hook up this event to the Command? I can't figure this out.

thanks in advance!

Bill

1
  • I should mention that I am using Josh Smith's RelayCommand as well. Commented Mar 4, 2010 at 21:54

5 Answers 5

43

The following code can be used to bind a shortcut key directly to a command:

<Window.InputBindings>
    <KeyBinding Command="{Binding Path=NameOfYourCommand}" 
                Key="O" 
                Modifiers="Control"/>
</Window.InputBindings>

Add this after Window.Resources in the XAML code of your view.

4
  • 4
    Yeah not sure what OP's problem was, but this works fine. (I'm using MVVM light)
    – GONeale
    Commented Aug 8, 2012 at 5:33
  • 10
    He specifically said this didn't work, and the selected answer explains why: He's not using WPF4. Not sure why you post his exact code as an "answer"
    – aaronburro
    Commented Sep 13, 2012 at 13:56
  • is the Modifiers Ctrl?
    – amit jha
    Commented May 21, 2017 at 13:52
  • 1
    @aaronburro OK answers and the question should be updated to mention WPF 4, but for those of us who even don't look at the question this answer is useful, and to be honest if I read the question I would be confused. Commented Feb 7, 2023 at 16:32
26

I wrote a custom markup extension to "bind" InputBindings to commands, which can be used almost like a real binding :

<UserControl.InputBindings>
    <KeyBinding Modifiers="Control" 
                Key="E" 
                Command="{input:CommandBinding EditCommand}"/>
</UserControl.InputBindings>

Note that this markup extension uses private reflection, so it can only be used if your application runs in full trust...

Another option is to use the CommandReference class. It can be found in the MVVM toolkit available here. It's probably a cleaner approach, but a bit more complex to use.

Note that in WPF 4, the InputBinding.Command, InputBinding.CommandParameter and InputBinding.CommandTarget properties are dependency properties, so they can be bound normally

8
  • I followed the exs in the WPF MVVM Docs - great examples! Exactly what I want to do. Unfortunately, the context menu items work fine, but the shortcut keys do nothing. I can't even figure out to debug this since nothing happens when I press the shortcut keys. Commented Mar 7, 2010 at 0:13
  • Could it be that I am trying to use these on shortcut keys on a ContextMenu instead of a standard menu? Commented Mar 7, 2010 at 0:16
  • which technique did you use ? the markup extension or the CommandReference class ? Commented Mar 7, 2010 at 0:18
  • The CommandReference - it does seem to matter where in the XAML I put the KeyBinding. If I put it in the DataGrid that is in the window I do hit the breakpoint in the CanExecute - but it seems to always return false. Commented Mar 7, 2010 at 1:57
  • I was thinking that if I put the KeyBinding anywhere in the window that it would work but that doesn't seem to be the case. Commented Mar 7, 2010 at 1:59
9

I agree that doing it in XAML is ideal, but for completeness sake, you could also add your binding in code. If you do it in the constructor, just make sure it is after the call to InitializeComponent()

InputBindings.Add(new KeyBinding(btnUpdate, new KeyGesture(Key.U, ModifierKeys.Control));
4
  • +1 This method allowed me to put it into my View because I needed the function to only work with UI elements.
    – CaptainBli
    Commented Feb 4, 2014 at 16:02
  • 3
    But this binds a button control, btnUpdate to the shortcut key Ctrl-U, not a to a command like Michel Keijzers's XAML does.
    – ProfK
    Commented Oct 23, 2014 at 12:53
  • 2
    I was answering the original post which was trying to bind to something called "btnUpdate".
    – Eddie Deyo
    Commented Oct 29, 2014 at 18:06
  • This works, but you have to replace btnUpdate with yourButton.Command.
    – EdgarT
    Commented Sep 20, 2015 at 2:42
0

An alternative approach for binding a WPF Shortcut Key to a Command property of the ViewModel is shown in the ShortcutKey sample of the WPF Application Framework (WAF) project.

2
  • Thanks ... I will need some time to look into it (meaning I don't have much time now but I upvoted because the link seems very useful (not only because of my question only). Commented Aug 8, 2012 at 9:03
  • This answer is only for propaganda, it doesn't give any help, neither does the given link Commented May 30, 2019 at 13:48
0

Have been able to add Keybinding on the DataGrid level. Like this :

Xaml :

<DataGrid 
                    AutoGenerateColumns="False"
                    ItemsSource="{Binding YourCollection}"                         
                    CanUserAddRows="False"                        
                    HeadersVisibility="Column" 
                    CanUserDeleteRows="False" 
                    CanUserSortColumns="True"
                    CanUserResizeRows="False"
                    CanUserResizeColumns="False"                       
                    SelectedItem="{Binding YourSelectedItem}" 
                    SelectionMode="Single" 
                    SelectionUnit="FullRow"
                   >
                <DataGrid.ContextMenu>
                    <ContextMenu>
                       **<MenuItem Header="Delete" InputGestureText="Del" Command="{Binding DeleteCommand}">**
                        </MenuItem>
                    </ContextMenu>
                </DataGrid.ContextMenu>
                **<DataGrid.InputBindings>
                    <KeyBinding Key="Delete" Command="{Binding DeleteCommand}" CommandParameter="Delete"/>**
                </DataGrid.InputBindings>
                <DataGrid.Columns>
                    <DataGridTextColumn Header="Column Header" Binding="{Binding YourColumn}" IsReadOnly="True" />
                </DataGrid.Columns>
</DataGrid>

View Model :

public ICommand DeleteCommand
            {
                get
                {
                    return new DelegateCommand(ExecuteCommand, CanExecute);
                }
            }

  private void ExecuteCommand()
{
// your code to delete here.
   YourCollection.Remove(YourSelectedItem);
}

private void CanExecute()
{
// logic to check if the delete command can execute.
   return YourSelectedItem != null ;
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.