如何使用触发器将事件参数传递给命令?

所以我有一个简单的设置,一个带有Populating事件的自动完成框,我想绑定到一个命令。 我用

clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity 

(这有更好的命名空间吗?)

绑定它并不是什么大不了的事,最重要的是将PopulatingEventArgs参数传递给bound命令。

那么如何根据PRISM的最佳实践和一般的MVVM来做到这一点呢?

没有内置方式,所以我这样做:

经典的Interaction触发器使用如下:

  

我们无法通过绑定访问MouseEnter事件的EventArgs ,因此我们将不得不修改将其抛弃的部分。
碰巧的是,那件作品是InvokeCommandAction

“所以我们只是将它子类化并覆盖一直等待我们的方便方法”是我想写的。 但课程是密封的。

所以我们必须inheritance它的父(抽象)类: TriggerAction

最基本的实现是:

 public class InteractiveCommand : TriggerAction { protected override void Invoke(object parameter) { } } 

那个parameter就是你的EventArgs
但坚持下去,并不是那么简单,我们必须重现常规InvokeCommandAction的行为。
通过Reflector,我反编译它(但你可以看看官方消息来源,我只是懒惰)。

我们不会关心CommandParameter依赖属性,我们假设如果你使用它而不是InvokeCommandAction ,你实际上每次都想要EventArgs

这里是完整的类(仅限WPF,请参阅SilverLight的EDIT):

 public class InteractiveCommand : TriggerAction { 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 } 

与您从互联网上获取的任何代码一样, 我强烈建议您阅读整个class级,并尝试了解它的作用 。 不要只是把它扔进你的应用程序。

现在我们可以做到:

  

而背后的代码:

 #region CommandWithEventArgs DelegateCommand _CommandWithEventArgs; ///  /// Exposes . ///  public DelegateCommand CommandWithEventArgs { get { return _CommandWithEventArgs ?? (_CommandWithEventArgs = new DelegateCommand(CommandWithEventArgs)); } } #endregion public void CommandWithEventArgs(MouseEventArgs param) { } 

这是一个包装;)

编辑:对于SilverLight,请改用以下代码:

  public class InteractiveCommand : TriggerAction { 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版本安全(不检查类型,可能会因冻结元素而崩溃)。

我尝试了InteractiveCommand,它给我带来了麻烦。 相反,我设置了对Microsoft.Expression.Interactions的引用并包含在内

 xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions"         

…在我的UserControl中。

然后将事件处理程序放在我的ViewModel中并将范围设置为public:

 public void ShowDialog(object sender, ShowDialogEventArgs e) { } public void AppointmentEditing(object sender, AppointmentEditingEventArgs e) { } 

到目前为止运作良好。