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>

其三,则是最最难受的,如果想获得事件参数,就得重写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);
        }
    }
}

三、使用

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

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

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

后端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)
        {
            
        }
    }
}

是不是很nice。

  • 9
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

若汝棋茗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值