背景
在我们进行WPF开发应用程序的时候不可避免的要使用到事件,很多时候没有严格按照MVVM模式进行开发的时候习惯直接在xaml中定义事件,然后再在对应的.cs文件中直接写事件的处理过程,这种处理方式写起来非常简单而且不用过多地处理考虑代码之间是否符合规范,但是我们在写代码的时候如果完全按照WPF规范的MVVM模式进行开发的时候就应该将相应的事件处理写在ViewModel层,这样整个代码才更加符合规范而且层次也更加清楚,更加符合MVVM规范。
常规用法
1 引入命名空间
通过在代码中引入System.Windows.Interactivity.dll,引入了这个dll后我们就能够使用这个里面的方法来将事件映射到ViewModel层了,我们来看看具体的使用步骤,第一步就是引入命名控件
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
另外还可以通过另外一种方式来引入命名空间,其实这两者间都是对等的。
xmlns:i=http://schemas.microsoft.com/expression/2010/interactivity
2 添加事件对应的Command
这里以TextBox的GetFocus和LostFocus为例来进行说明
<TextBox Text="CommandBinding">
<i:Interaction.Triggers>
<i:EventTrigger EventName="LostFocus">
<i:InvokeCommandAction Command="{Binding OnTextLostFocus}"
CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type TextBox}}}"/>
</i:EventTrigger>
<i:EventTrigger EventName="GotFocus">
<i:InvokeCommandAction Command="{Binding OnTextGotFocus}"
CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type TextBox}}}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
这个里面我们重点来看看这个InvokeCommandAction的代码结构
namespace System.Windows.Interactivity
{
public sealed class InvokeCommandAction : TriggerAction<DependencyObject>
{
public static readonly DependencyProperty CommandProperty;
public static readonly DependencyProperty CommandParameterProperty;
public InvokeCommandAction();
public string CommandName { get; set; }
public ICommand Command { get; set; }
public object CommandParameter { get; set; }
protected override void Invoke(object parameter);
}
}
这里我们发现这里我们如果我们定义一个Command的话我们只能够在Command中获取到我们绑定的CommandParameter这个参数,但是有时候我们需要获取到触发这个事件的RoutedEventArgs的时候,通过这种方式就很难获取到了,这个时候我们就需要自己去扩展一个InvokeCommandAction了,这个时候我们应该怎么做呢?整个过程分成三步:
2.1 定义自己的CommandParameter
public class ExCommandParameter
{
/// <summary>
/// 事件触发源
/// </summary>
public DependencyObject Sender { get; set; }
/// <summary>
/// 事件参数
/// </summary>
public EventArgs EventArgs { get; set; }
/// <summary>
/// 额外参数
/// </summary>
public object Parameter { get; set; }
}
这个对象除了封装我们常规的参数外还封装了我们需要的EventArgs属性,有了这个我们就能将当前的事件的EventArgs传递进来了。
2.2 重写自己的InvokeCommaй5 |