Binding Commands to Events?

前端 未结 6 2072
清歌不尽
清歌不尽 2020-12-01 06:57

What\'s a good method to bind Commands to Events? In my WPF app, there are events that I\'d like to capture and process by my ViewModel but I\'m not sure how. Things like lo

6条回答
  •  渐次进展
    2020-12-01 07:42

    I implemented it using Attached Properties and Reflection. I cannot say it is the best implementation, but I will maybe improve it and it may be a good start for you.

    public class EventBinding : DependencyObject
    {
        public static string GetEventName(DependencyObject obj)
        {
            return (string)obj.GetValue(EventNameProperty);
        }
    
        public static void SetEventName(DependencyObject obj, string value)
        {
            obj.SetValue(EventNameProperty, value);
            var eventInfo = obj.GetType().GetEvent(value);
            var eventHandlerType = eventInfo.EventHandlerType;
            var eventHandlerMethod = typeof(EventBinding).
                GetMethod("EventHandlerMethod", BindingFlags.Static | BindingFlags.NonPublic);
            var eventHandlerParameters = eventHandlerType.GetMethod("Invoke").GetParameters();
            var eventArgsParameterType = eventHandlerParameters.
                Where(p => typeof(EventArgs).IsAssignableFrom(p.ParameterType)).
                Single().ParameterType;
            eventHandlerMethod = eventHandlerMethod.MakeGenericMethod(eventArgsParameterType);
            eventInfo.AddEventHandler(obj, Delegate.CreateDelegate(eventHandlerType, eventHandlerMethod));
        }
    
        private static void EventHandlerMethod(object sender, TEventArgs e)
            where TEventArgs : EventArgs
        {
            var command = GetCommand(sender as DependencyObject);
            command.Execute(new EventInfo(sender, e));
        }
    
        public static readonly DependencyProperty EventNameProperty = 
            DependencyProperty.RegisterAttached("EventName", typeof(string), typeof(EventHandler));
    
        public static ICommand GetCommand(DependencyObject obj)
        {
            return (ICommand)obj.GetValue(CommandProperty);
        }
    
        public static void SetCommand(DependencyObject obj, ICommand value)
        {
            obj.SetValue(CommandProperty, value);
        }
    
        public static readonly DependencyProperty CommandProperty =
            DependencyProperty.RegisterAttached("Command", typeof(ICommand), typeof(EventBinding));
    
    }
    
    public class EventInfo
    {
        public object Sender { get; set; }
        public TEventArgs EventArgs { get; set; }
    
        public EventInfo(object sender, TEventArgs e)
        {
            Sender = sender;
            EventArgs = e;
        }
    }
    
    public class EventInfo : EventInfo
    {
        public EventInfo(object sender, EventArgs e)
            : base(sender, e) { }
    }
    
    public class EventBindingCommand : RelayCommand>
        where TEventArgs : EventArgs
    {
        public EventBindingCommand(EventHandler handler)
            : base(info => handler(info.Sender, info.EventArgs)) { }
    }
    

    Examples of usage:

    View

    
    

    Model

    private EventBindingCommand _cellEditEndingCommand;
    
    public EventBindingCommand CellEditEndingCommand
    {
        get 
        { 
            return _cellEditEndingCommand ?? (
                _cellEditEndingCommand = new EventBindingCommand(CellEditEndingHandler)); 
        }
    }
    
    public void CellEditEndingHandler(object sender, DataGridCellEditEndingEventArgs e)
    {
        MessageBox.Show("Test");
    }
    

提交回复
热议问题