Best Practices: How to implement ShortCut Keys with DelegateCommands

Coordinator
Apr 11, 2009 at 3:28 PM
Edited Apr 12, 2009 at 5:37 PM

When I had to implement ShortCut Keys (e.g. Ctrl+O) for my DelegateCommands I thought this should be a no-brainer and be done in five minutes. Unfortunately, it started soon to become a bit more difficult to implement.
 
I have defined a menu for my application like the one in the code snippet below. The “Open…” menu item binds the Command to the OpenCommand property of the PresentationModel. The PresentationModel was set as DataContext to the Window. So far all works fine.
 
<Menu DockPanel.Dock="Top">
    <MenuItem Header="_File">
        <MenuItem Header="_Open..." Command="{Binding OpenCommand}" InputGestureText="Ctrl+O"/>
    </MenuItem>
</Menu>
  
The MenuItem class has a property called InputGestureText. If you are familiar with the ToolStripMenu of Windows Forms then you might think (as I have done) that it is enough to define this property with the shortcut key. I had to learn that this property only shows the value as additional text in the menu item and doesn’t have any effect on the WPF key bindings. Note: The InputGestureText needs to be localized as well.
 
Then I defined a key binding for the Ctrl+O shortcut key like this:
 
<Window.InputBindings>
    <KeyBinding Command="{Binding OpenCommand}"  Modifiers="Control" Key="O"/>
</Window.InputBindings>
 
The XAML definition looks correct but the compiler shows an error because the Command property of the KeyBinding class is not a DependencyProperty and so you cannot use a Binding here.
 
I thought that I’m able to solve this problem by just inheriting my own “ShortCutKey” class from KeyBinding and define a DependencyProperty called “BindableCommand”. But this doesn’t work either because the KeyBindings are not part of the WPF element tree (either visual or logical tree). For that reason, the binding engine isn’t able to access the DataContext property of the Window where the PresentationModel is set.
 
My final implementation is quite simple but needs some lines of code in the XAML code behind class.
 
<Window.InputBindings>
    <KeyBinding x:Name="openKeyBinding" Modifiers="Control" Key="O"/>
</Window.InputBindings>
 
 
public partial class ShellWindow : Window
{
    public ShellWindow()
    {
        InitializeComponent();
        DataContextChanged += ThisDataContextChanged;
    }

    private ShellPresentationModel PresentationModel { get { return DataContext as ShellPresentationModel; } }

    private void ThisDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        openKeyBinding.Command = PresentationModel.OpenCommand;
    }
}
 
In the code example above I hear on the DataContextChanged event. When this one occurs then I now that the ShellPresentationModel was set and I can set the OpenCommand property to my key binding. That’s all. :-)
 
 
Code download: http://compositeextensions.codeplex.com/Release/ProjectReleases.aspx?ReleaseId=26019 

Jul 2, 2009 at 11:56 AM

Hi

I am wondering if there is a way to capture the Keystroke for PrintScrn using KeyBinding.

Any suggestions will be appreciated.

Thanks

Navin