没有内置方法,所以我是这样做的:
经典的交互触发器是这样使用的:
<Button Content="I am a button">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<i:InvokeCommandAction Command="{Binding CommandWithNoArgs}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
我们无法通过绑定访问MouseEnter 事件的EventArgs,因此我们将不得不修改将其丢弃的部分。
碰巧,那块是InvokeCommandAction。
“所以我们只是将它子类化并覆盖一个一直在等待我们的便捷方法”是我想写的。但是这个类是密封的。
所以我们将不得不继承它的父(抽象)类:TriggerAction<DependencyObject>
最基本的实现是:
public class InteractiveCommand : TriggerAction<DependencyObject>
{
protected override void Invoke(object parameter)
{
}
}
而parameter 就是你的EventArgs!
但是等等,事情没那么简单,我们必须重现普通InvokeCommandAction 的行为。
通过Reflector,我反编译了(不过你可以去看看官方源码,我就是懒)。
我们不会关心 CommandParameter 依赖属性,我们会假设如果您使用它而不是 InvokeCommandAction,那么您实际上每次都需要 EventArgs。
这是完整的课程(仅限 WPF,请参阅 SilverLight 的编辑):
public class InteractiveCommand : TriggerAction<DependencyObject>
{
protected override void Invoke(object parameter)
{
if (base.AssociatedObject != null)
{
ICommand command = this.ResolveCommand();
if ((command != null) && command.CanExecute(parameter))
{
command.Execute(parameter);
}
}
}
private ICommand ResolveCommand()
{
ICommand command = null;
if (this.Command != null)
{
return this.Command;
}
if (base.AssociatedObject != null)
{
foreach (PropertyInfo info in base.AssociatedObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
if (typeof(ICommand).IsAssignableFrom(info.PropertyType) && string.Equals(info.Name, this.CommandName, StringComparison.Ordinal))
{
command = (ICommand)info.GetValue(base.AssociatedObject, null);
}
}
}
return command;
}
private string commandName;
public string CommandName
{
get
{
base.ReadPreamble();
return this.commandName;
}
set
{
if (this.CommandName != value)
{
base.WritePreamble();
this.commandName = value;
base.WritePostscript();
}
}
}
#region Command
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
// Using a DependencyProperty as the backing store for Command. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(InteractiveCommand), new UIPropertyMetadata(null));
#endregion
}
与您从互联网上获取的任何代码一样,我强烈建议您通读整个课程,并尝试了解它的作用。不要只是把它扔到你的应用程序中。
现在我们可以这样做了:
<Button Content="I am a button">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<local:InteractiveCommand Command="{Binding CommandWithEventArgs}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
以及背后的代码:
#region CommandWithEventArgs
DelegateCommand<MouseEventArgs> _CommandWithEventArgs;
/// <summary>
/// Exposes <see cref="CommandWithEventArgs(MouseEventArgs)"/>.
/// </summary>
public DelegateCommand<MouseEventArgs> CommandWithEventArgs
{
get { return _CommandWithEventArgs ?? (_CommandWithEventArgs = new DelegateCommand<MouseEventArgs>(CommandWithEventArgs)); }
}
#endregion
public void CommandWithEventArgs(MouseEventArgs param)
{
}
这是一个包装;)
编辑:对于 SilverLight,请改用以下代码:
public class InteractiveCommand : TriggerAction<DependencyObject>
{
protected override void Invoke(object parameter)
{
if (base.AssociatedObject != null)
{
ICommand command = Command;
if ((command != null) && command.CanExecute(parameter))
{
command.Execute(parameter);
}
}
}
#region Command
public ICommand Command
{
get { return (ICommand)GetValue(CommandProperty); }
set { SetValue(CommandProperty, value); }
}
// Using a DependencyProperty as the backing store for Command. This enables animation, styling, binding, etc...
public static readonly DependencyProperty CommandProperty =
DependencyProperty.Register("Command", typeof(ICommand), typeof(InteractiveCommand), new UIPropertyMetadata(null));
#endregion
}
但请注意,它不如使用完整的 WPF 版本安全(不检查类型,可能会因冻结元素而崩溃)。