Wp&Win8中使用命令绑定时,除了Button控件自带命令绑定,其他的时候是用Interactivity库中的InvokeCommandAction实现的(Win8 需要额外安装第三方NuGet包才可使用,我的MVFM示例博客中带有这个库),但使用过程中发现InvokeCommandAction并不能满足我们的要求,主要有以下几点:
1 无法获取发送者;
2 用EventTrigger触发时往往需要用到EventArg参数,但是InvokeCommandAction无法获取;
3 有时需要传递多个参数,无法满足;
于是我对InvokeCommandAction进行了一些改进,首先定义参数的结构体:
/// <summary> /// 扩展CommandParameter,使CommandParameter可以带事件参数 /// </summary> public class ExCommandParameter { /// <summary> /// 事件触发源 /// </summary> public object Sender { get; set; } /// <summary> /// 事件参数 /// </summary> public object EventArgs { get; set; } /// <summary> /// 参数 /// </summary> public object Parameter { get; set; } /// <summary> /// 扩展参数 /// </summary> public object Parameter2 { get; set; } /// <summary> /// 扩展参数 /// </summary> public object Parameter3 { get; set; } }
然后定义处理的TriggerAction:
/// <summary> /// 扩展的InvokeCommandAction /// </summary> public class ExInvokeCommandAction : CustomTriggerActionBase { 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); public static readonly DependencyProperty CommandParameter2Property = DependencyProperty.Register("CommandParameter2", typeof(object), typeof(ExInvokeCommandAction), null); public static readonly DependencyProperty CommandParameter3Property = DependencyProperty.Register("CommandParameter3", typeof(object), typeof(ExInvokeCommandAction), null); /// <summary> /// 获得或设置此操作应调用的命令的名称。 /// </summary> /// <value>此操作应调用的命令的名称。</value> /// <remarks>如果设置了此属性和 Command 属性,则此属性将被后者所取代。</remarks> public string CommandName { get { return this.commandName; } set { if (this.commandName != value) { this.commandName = value; } } } /// <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); } } public object CommandParameter2 { get { return base.GetValue(ExInvokeCommandAction.CommandParameter2Property); } set { base.SetValue(ExInvokeCommandAction.CommandParameter2Property, value); } } public object CommandParameter3 { get { return base.GetValue(ExInvokeCommandAction.CommandParameter3Property); } set { base.SetValue(ExInvokeCommandAction.CommandParameter3Property, value); } } /// <summary> /// 调用操作。 /// </summary> /// <param name="parameter">操作的参数。如果操作不需要参数,则可以将参数设置为空引用。</param> protected override void Invoke(object parameter) { ICommand command = this.ResolveCommand(); ExCommandParameter exParameter = new ExCommandParameter { Sender = this.AssociatedObject, Parameter = GetValue(CommandParameterProperty), Parameter2 = GetValue(CommandParameter2Property), Parameter3 = GetValue(CommandParameter3Property), EventArgs = parameter }; if (command != null && command.CanExecute(exParameter)) { command.Execute(exParameter); } } //手动触发 public void TriggerCommand() { Invoke(null); } public void TriggerCommand(object CommandParameter) { TriggerCommand(null, CommandParameter); } public void TriggerCommand(object sender = null, object commandParameter = null, object commandParameter2 = null, object commandParameter3 = null) { this.CommandParameter = commandParameter; this.CommandParameter2 = commandParameter2; this.CommandParameter3 = commandParameter3; Invoke(null); } protected ICommand ResolveCommand() { ICommand result = null; if (this.Command != null) { result = this.Command; } else { foreach (PropertyInfo propertyInfo in this.AssociatedObject.GetType().GetTypeInfo().DeclaredProperties) { if (typeof(ICommand).GetTypeInfo().IsAssignableFrom(propertyInfo.PropertyType.GetTypeInfo()) && string.Equals(propertyInfo.Name, this.CommandName, StringComparison.Ordinal)) { result = (ICommand)propertyInfo.GetValue((object)this.AssociatedObject, (object[])null); } } } return result; } }
使用时和InvokeCommandAction是一样的:
<i:Interaction.Triggers> <i:EventTrigger EventName="Loaded"> <Behavior:ExInvokeCommandAction Command="{Binding Command,Source={StaticResource ViewModel}}" CommandParameter="1" CommandParameter2="2" CommandParameter3="3"/> </i:EventTrigger> </i:Interaction.Triggers>