一般情况下,如果想实现事件绑定,网上的教程一般都是依赖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。