How can I handle the Keyboard.KeyDown event without using code-behind? We are trying to use the MVVM pattern and avoid writing an event handler in code-behind file.
I know this question is very old, but I came by this because this type of functionality was just made easier to implement in Silverlight (5). So maybe others will come by here too.
I wrote this simple solution after I could not find what I was looking for. Turned out it was rather simple. It should work in both Silverlight 5 and WPF.
public class KeyToCommandExtension : IMarkupExtension
{
public string Command { get; set; }
public Key Key { get; set; }
private void KeyEvent(object sender, KeyEventArgs e)
{
if (Key != Key.None && e.Key != Key) return;
var target = (FrameworkElement)sender;
if (target.DataContext == null) return;
var property = target.DataContext.GetType().GetProperty(Command, BindingFlags.Public | BindingFlags.Instance, null, typeof(ICommand), new Type[0], null);
if (property == null) return;
var command = (ICommand)property.GetValue(target.DataContext, null);
if (command != null && command.CanExecute(Key))
command.Execute(Key);
}
public Delegate ProvideValue(IServiceProvider serviceProvider)
{
if (string.IsNullOrEmpty(Command))
throw new InvalidOperationException("Command not set");
var targetProvider = (IProvideValueTarget)serviceProvider.GetService(typeof(IProvideValueTarget));
if (!(targetProvider.TargetObject is FrameworkElement))
throw new InvalidOperationException("Target object must be FrameworkElement");
if (!(targetProvider.TargetProperty is EventInfo))
throw new InvalidOperationException("Target property must be event");
return Delegate.CreateDelegate(typeof(KeyEventHandler), this, "KeyEvent");
}
Usage:
Notice that Command
is a string and not an bindable ICommand
. I know this is not as flexible, but it is cleaner when used, and what you need 99% of the time. Though it should not be a problem to change.