Keyboard events in a WPF MVVM application?

前端 未结 8 1905
情深已故
情深已故 2020-11-27 11:30

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.

8条回答
  •  抹茶落季
    2020-11-27 11:54

    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.

提交回复
热议问题