因此,我有一个简单的设置,即一个我希望绑定(bind)到命令的自动完成框及其填充事件。我用

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

(是否有更好的命名空间来执行此操作?)

绑定(bind)它并不重要,重要的是将PopulatingEventArgs参数传递给绑定(bind)的命令。

那么,如何根据PRISM的最佳实践以及一般的MVVM做到这一点?

最佳答案

没有内置的方法,所以这是我的方法:

经典的交互触发器的用法如下:

<Button Content="I am a button">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseEnter">
            <i:InvokeCommandAction Command="{Binding CommandWithNoArgs}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</Button>

我们无法通过绑定(bind)访问EventArgs事件的MouseEnter,因此我们将不得不修改将其扔掉的片段。
碰巧的是InvokeCommandAction

“所以我们只是将其子类化,并覆盖一直在等待我们的便捷方法”,这是我想要编写的。但是类(class)是密封的。

因此,我们将不得不对其父类(抽象类)进行子类化:TriggerAction<DependencyObject>
最基本的实现是:
public class InteractiveCommand : TriggerAction<DependencyObject>
{
    protected override void Invoke(object parameter)
    {
    }
}

parameter是您的EventArgs!
但是,不要紧,这不是那么简单,我们必须重现常规InvokeCommandAction的行为。
我通过Reflector对其进行了反编译(但是您可以去看看官方消息,我只是懒惰)。

我们不需要关心CommandParameter的依赖项属性,而是假设如果您使用它而不是InvokeCommandAction,则实际上每次都需要EventArgs

这是完整的类(仅WPF,请参阅EDIT for 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
}

就像您从Internet上获取的任何代码一样,我强烈建议阅读整个类(class),并试图了解的作用。不要只是将它扔到您的应用程序中。

现在我们可以做:
<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版本安全(不检查类型,可能因冻结的元素而崩溃)。

关于c# - 如何使用触发器将事件参数传递给命令?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13565484/

10-09 18:23
查看更多