• WPF实现超简约的MVVM事件绑定(不依赖任何东西)



    一、常规实现

    一般情况下,如果想实现事件绑定,网上的教程一般都是依赖Microsoft.Xaml.Interactions。但是我本人很不喜欢这东西。

    其一,需要引入一个dll。
    在这里插入图片描述
    其二,你的前端xaml将会变得这样:

    <Button Content="xxx"  Width="120" Height="40" >
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="MouseDoubleClick">
                <i:InvokeCommandAction Command="{Binding Btncommand}"  CommandParameter="read" />
            </i:EventTrigger>
            <i:EventTrigger EventName="Click">
                <i:InvokeCommandAction Command="{Binding Btncommand}"  CommandParameter="read" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    
    </Button>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    其三,则是最最难受的,如果想获得事件参数,就得重写CommandAction

    嘶,,我这引入了一个dll,还得自己再写个类,为的就仅仅是绑定一个事件??

    那有没有更简单的方法呢?

    有。

    二、简约风实现

    以下就是全部代码。

    //------------------------------------------------------------------------------
    //  此代码版权(除特别声明或在XREF结尾的命名空间的代码)归作者本人若汝棋茗所有
    //  源代码使用协议遵循本仓库的开源协议及附加协议,若本仓库没有设置,则按MIT开源协议授权
    //  CSDN博客:https://blog.csdn.net/qq_40374647
    //  哔哩哔哩视频:https://space.bilibili.com/94253567
    //  Gitee源代码仓库:https://gitee.com/RRQM_Home
    //  Github源代码仓库:https://github.com/RRQM
    //  API首页:https://www.yuque.com/rrqm/touchsocket/index
    //  交流QQ群:234762506
    //  感谢您的下载和使用
    //------------------------------------------------------------------------------
    //------------------------------------------------------------------------------
    using System;
    using System.Collections;
    using System.Collections.Generic;
    using System.Reflection;
    using System.Windows;
    
    namespace TouchMvvm
    {
        public interface IEventAction
        {
            string EventName { get; }
        }
    
        public static class EventCommands
        {
            // Using a DependencyProperty as the backing store for Events.  This enables animation, styling, binding, etc...
            public static readonly DependencyProperty EventsProperty =
                DependencyProperty.RegisterAttached("Events", typeof(IEnumerable<IEventAction>), typeof(EventCommands), new PropertyMetadata(null, OnCommandChanged));
    
            public static IEnumerable<IEventAction> GetEvents(DependencyObject obj)
            {
                return (IEnumerable<IEventAction>)obj.GetValue(EventsProperty);
            }
    
            public static void SetEvents(DependencyObject obj, IEnumerable<IEventAction> value)
            {
                obj.SetValue(EventsProperty, value);
            }
    
            private static void OnCommandChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
            {
                if (e.NewValue is IEnumerable eventActions)
                {
                    foreach (IEventAction eventAction in eventActions)
                    {
                        if (!string.IsNullOrEmpty(eventAction.EventName))
                        {
                            EventInfo eventInfo = d.GetType().GetEvent(eventAction.EventName);
                            if (eventInfo == null)
                            {
                                throw new Exception($"没有找到名称为{eventAction.EventName}的事件");
                            }
                            Delegate @delegate = Delegate.CreateDelegate(eventInfo.EventHandlerType, eventAction, "Event");
                            //Delegate @delegate2 = eventAction.Begin(eventInfo.EventHandlerType, typeof(object), typeof(MouseButtonEventArgs));
                            //Delegate @delegate = DelegateBuilder.CreateDelegate(eventAction, "Event", eventInfo.EventHandlerType, BindingFlags.NonPublic);
                            eventInfo.AddEventHandler(d, @delegate);
                        }
                        else
                        {
                            throw new Exception($"事件名不能为空");
                        }
                    }
                }
            }
        }
    
        public class EventAction<TSender, TE> : IEventAction
        {
            private readonly Action<TSender, TE> action;
    
            private readonly string eventName;
    
            public EventAction(string eventName, Action<TSender, TE> action)
            {
                this.eventName = eventName;
                this.action = action;
            }
    
            public string EventName => this.eventName;
    
            private void Event(TSender sender, TE e)
            {
                this.action?.Invoke(sender, e);
            }
        }
    
        public class EventAction<TE> : IEventAction
        {
            private readonly Action<object> action;
    
            private readonly Action<TE> action2;
    
            private readonly string eventName;
    
            public EventAction(string eventName, Action<object> action)
            {
                this.eventName = eventName;
                this.action = action;
            }
    
            public EventAction(string eventName, Action<TE> action)
            {
                this.eventName = eventName;
                this.action2 = action;
            }
    
            public string EventName => this.eventName;
    
            private void Event(object sender, TE e)
            {
                this.action?.Invoke(sender);
                this.action2?.Invoke(e);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117

    三、使用

    使用非常简单,下列,我就以DataGrid的双击事件和选择项改变事件为例。

    你的前端,首先需要引入touchMvvm的命名空间,然后DataGridActionsCommand能够连接你的VM即可。

    <DataGrid  touchMvvm:EventCommands.Events="{Binding DataGridActionsCommand}"/>
    
    • 1

    后端VM代码。
    如果想要更多的事件,前端不用动,只需要增加对应事件的EventAction即可。

    public class ViewModel : ViewModelBase
    {
        public ViewModel()
        {
            this.DataGridActionsCommand = new IEventAction[]
            {
                new EventAction<MouseButtonEventArgs>("MouseDoubleClick", DataGridMouseDoubleClick) ,
                new EventAction<object,SelectionChangedEventArgs>("SelectionChanged", DataGridSelectionChanged)
            };
        }
        public IEventAction[] DataGridActionsCommand { get; set; }
    
        private void DataGridMouseDoubleClick(MouseButtonEventArgs e)
        {
        }
    
        private void DataGridSelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if (sender is DataGrid dataGrid)
            {
                
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    是不是很nice。

  • 相关阅读:
    面向对象分析与设计好文章
    ios证书类型及其作用说明
    数据治理:微服务架构下的数据治理
    在Microsoft Exchange Server 2007中安装SSL证书的教程
    【AAAI2022】Efficient Non-Local Contrastive Attention for Image Super-Resolution
    向数据报表添加一个合计字段
    星火大模型AI接口Spring中项目中使用【星火、AIGC】
    【机器学习】聚类算法中的距离度量有哪些及公式表示?
    【无标题】
    WSL重装Anaconda
  • 原文地址:https://blog.csdn.net/qq_40374647/article/details/127651804