How to bind custom ICommands to Input Bindings

If you are developing using any sort of V-VM-M pattern, you are already loving the awesome binding powers of Wpf.

And you should also be loving ICommand and binding buttons to ICommand properties on your VM.

What you might have discovered is that binding ICommands to Keys and other input gestures is not as easy as it was with vanilla Routed Commands.

But have no fear! There is a solution.

By utilizing Josh Smith’s Element Spy trick and creating a custom InputBinding, we can gain the functionality of binding an ICommand to a Key, etc.

Here is my custom input binding :

 

   1: public class MyInputBinding : KeyBinding
   2: {
   3:     #region Fields
   4:  
   5:     private static readonly DependencyProperty BoundCommandProperty = 
   6:                     DependencyProperty.Register("BoundCommand",
   7:                                                 typeof (ICommand),
   8:                                                 typeof (MyInputBinding),
   9:                                                 new PropertyMetadata(OnBoundCommandChanged));
  10:  
  11:     #endregion
  12:  
  13:     #region Properties
  14:  
  15:     public ICommand BoundCommand
  16:     {
  17:         get { return GetValue(BoundCommandProperty) as ICommand; }
  18:         set { SetValue(BoundCommandProperty, value);}
  19:     }
  20:  
  21:     #endregion
  22:  
  23:     #region Methods
  24:  
  25:     private static void OnBoundCommandChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
  26:     {
  27:         MyInputBinding binding = obj as MyInputBinding;
  28:  
  29:         if (binding == null) return;
  30:  
  31:         binding.Command = e.NewValue as ICommand;
  32:     }
  33:  
  34:     #endregion
  35: }

Then when you combine the use of the ElementSpy, your xaml looks like:

<Window.Resources>

    <InputBindingSandbox:ElementSpy x:Key="spy" />

</Window.Resources>


<Window.InputBindings>

    <InputBindingSandbox:MyInputBinding BoundCommand="{Binding Source={StaticResource spy},

                                                               Path=Element.DataContext.MyCommand}"

                                        Key="Enter" />

</Window.InputBindings>

Naturally the custom input binding is very simple and does not expose the Command Parameter nor the Command Target, etc. But the basic pattern is there so feel free to utilize and extend.

Happy coding!

JB

Advertisements