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>