<Window x:Class="EventArgsInViewModel.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:loc="clr-namespace:EventArgsInViewModel"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<loc:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Button Content="Button" Height="38" HorizontalAlignment="Left" Margin="50,52,0,0" Name="button1" VerticalAlignment="Top" Width="138">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction
Command="{Binding ClickCommand}" CommandParameter="{Binding ElementName=button1}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
</Window>

现在为了扩展CommandParameter,定义ExCommandParameter类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;

namespace EventArgsInViewModel {
/// <summary>
/// 扩展CommandParameter,使CommandParameter可以带事件参数
/// </summary>
public class ExCommandParameter {
/// <summary>
/// 事件触发源
/// </summary>
public DependencyObject Sender { get; set; }
/// <summary>
/// 事件参数
/// </summary>
public EventArgs EventArgs { get; set; }
/// <summary>
/// 额外参数
/// </summary>
public object Parameter { get; set; }
}
}

然后定义ExInvokeCommandAction类,用于扩展InvokeCommandAction

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Interactivity;
using System.Windows.Input;
using System.Reflection;

namespace EventArgsInViewModel {
/// <summary>
/// 扩展的InvokeCommandAction
/// </summary>
public class ExInvokeCommandAction : TriggerAction<DependencyObject> {

private string commandName;
public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(ExInvokeCommandAction), null);
public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(ExInvokeCommandAction), null);
/// <summary>
/// 获得或设置此操作应调用的命令的名称。
/// </summary>
/// <value>此操作应调用的命令的名称。</value>
/// <remarks>如果设置了此属性和 Command 属性,则此属性将被后者所取代。</remarks>
public string CommandName {
get {
base.ReadPreamble();
return this.commandName;
}
set {
if (this.CommandName != value) {
base.WritePreamble();
this.commandName = value;
base.WritePostscript();
}
}
}
/// <summary>
/// 获取或设置此操作应调用的命令。这是依赖属性。
/// </summary>
/// <value>要执行的命令。</value>
/// <remarks>如果设置了此属性和 CommandName 属性,则此属性将优先于后者。</remarks>
public ICommand Command {
get {
return (ICommand)base.GetValue(ExInvokeCommandAction.CommandProperty);
}
set {
base.SetValue(ExInvokeCommandAction.CommandProperty, value);
}
}
/// <summary>
/// 获得或设置命令参数。这是依赖属性。
/// </summary>
/// <value>命令参数。</value>
/// <remarks>这是传递给 ICommand.CanExecute 和 ICommand.Execute 的值。</remarks>
public object CommandParameter {
get {
return base.GetValue(ExInvokeCommandAction.CommandParameterProperty);
}
set {
base.SetValue(ExInvokeCommandAction.CommandParameterProperty, value);
}
}
/// <summary>
/// 调用操作。
/// </summary>
/// <param name="parameter">操作的参数。如果操作不需要参数,则可以将参数设置为空引用。</param>
protected override void Invoke(object parameter) {
if (base.AssociatedObject != null) {
ICommand command = this.ResolveCommand();

/*
* ★★★★★★★★★★★★★★★★★★★★★★★★
* 注意这里添加了事件触发源和事件参数
* ★★★★★★★★★★★★★★★★★★★★★★★★
*/
ExCommandParameter exParameter = new ExCommandParameter {
Sender=base.AssociatedObject,
Parameter = GetValue(CommandParameterProperty),
EventArgs=parameter as EventArgs

};

if (command != null && command.CanExecute(exParameter)) {
/*
* ★★★★★★★★★★★★★★★★★★★★★★★★
* 注意将扩展的参数传递到Execute方法中
* ★★★★★★★★★★★★★★★★★★★★★★★★
*/
command.Execute(exParameter);
}
}
}
private ICommand ResolveCommand() {
ICommand result = null;
if (this.Command != null) {
result = this.Command;
} else {
if (base.AssociatedObject != null) {
Type type = base.AssociatedObject.GetType();
PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public);
PropertyInfo[] array = properties;
for (int i = 0; i < array.Length; i++) {
PropertyInfo propertyInfo = array[i];
if (typeof(ICommand).IsAssignableFrom(propertyInfo.PropertyType) && string.Equals(propertyInfo.Name, this.CommandName, StringComparison.Ordinal)) {
result = (ICommand)propertyInfo.GetValue(base.AssociatedObject, null);
}
}
}
}
return result;
}

}
}

好了,我们把xaml改一下,现在改用我们自己创建的ExInvokeCommandAction

<Window x:Class="EventArgsInViewModel.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:loc="clr-namespace:EventArgsInViewModel"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<loc:MainWindowViewModel />
</Window.DataContext>
<Grid>
<Button Content="Button" Height="38" HorizontalAlignment="Left" Margin="50,52,0,0" Name="button1" VerticalAlignment="Top" Width="138">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<!--★★★扩展的InvokeCommandAction★★★-->
<loc:ExInvokeCommandAction
Command="{Binding ClickCommand}" CommandParameter="{Binding ElementName=button1}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</Grid>
</Window>

ViewModel代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using Microsoft.Practices.Prism.Commands;
using System.Windows;

namespace EventArgsInViewModel {
public class MainWindowViewModel {
public ICommand ClickCommand {
get {
return new DelegateCommand<ExCommandParameter>((p) => {
RoutedEventArgs args = p.EventArgs as RoutedEventArgs;
MessageBox.Show(args.ToString());
},
(p) => {
return true;
}
);
}
}
}
}

现在点击一下按钮,显示了对应的消息框,OK,参数也能得到。是不是也很容易啊。
那么有人问,除了ExInvokeCommandAction我也会,但是ExInvokeCommandAction让人想破脑袋也不会写。其实,我也不会写,我只是用ILSpy反编译了一下,然后稍稍改动而已(这个我还是可以做到的)。
最后我想说:“其实你只要动脑筋都做到的事很多!
————————————————
版权声明:本文为CSDN博主「qing2005」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qing2005/article/details/6680047