Tuesday, March 01, 2011

Using InputBindings with the MVVM pattern

If you develop WPF applications according to the Model-View-ViewModel pattern, you may have faced this issue : in XAML, how to bind a key or mouse gesture to a ViewModel command ? The obvious and intuitive approach would be this one :

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

Unfortunately, this code doesn’t work, for two reasons :

  1. The Command property is not a dependency property, so you cannot assign it through binding
  2. InputBindings are not part of the logical or visual tree of the control, so they don’t inherit the DataContext
A solution would be to create the InputBindings in the code-behind, but in the MVVM pattern we usually prefer to avoid this… I spent a long time looking for alternative solutions to do this in XAML, but most of them are quite complex and unintuitive. So I eventually came up with a markup extension that enables binding to ViewModel commands, anywhere in XAML, even for non-dependency properties or if the element doesn’t normally inherit the DataContext
This extension is used like a regular binding :

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

(The input XML namespace is mapped to the CLR namespace where the markup extension is declared)
In order to write this extension, I had to cheat a little… I used Reflector to find some private fields that would allow to retrieve the DataContext of the root element. I then accessed those fields using reflection.
Here is the code of the markup extension :

Read more: Thomas Levesque's .NET blog