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

C# 如何使用触发器将事件参数传递给命令?,c#,events,mvvm,silverlight-4.0,icommand,C#,Events,Mvvm,Silverlight 4.0,Icommand,因此,我有一个简单的设置,一个带有填充事件的自动完成框,我想绑定到一个命令。我用 clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity (有更好的名称空间吗?) 绑定它没什么大不了的,重要的是将PopulatingEventArgs参数传递给绑定命令 那么,我如何根据PRISM的最佳实践和MVVM的最佳实践来做这件事呢?没有内置的方法,所以我是这样做的: 经典交互触发器的使用方式如下:

因此,我有一个简单的设置,一个带有填充事件的自动完成框,我想绑定到一个命令。我用

clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity 
(有更好的名称空间吗?)

绑定它没什么大不了的,重要的是将PopulatingEventArgs参数传递给绑定命令


那么,我如何根据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>
而这个
参数
就是您的
事件参数

但是,等等,这并不是那么简单,我们必须重现常规的
InvokeCommandAction

通过Reflector,我反编译了它(但是你可以去看看官方的源代码,我只是很懒)

我们不关心
CommandParameter
依赖属性,我们将假设如果您使用此属性而不是
InvokeCommandAction
,那么实际上每次都需要
EventArgs

下面是完整的类(仅限WPF,请参见SilverLight的编辑):

公共类交互命令:TriggerAction
{
受保护的覆盖无效调用(对象参数)
{
if(base.AssociatedObject!=null)
{
ICommand command=this.ResolveCommand();
if((command!=null)&&command.CanExecute(参数))
{
command.Execute(参数);
}
}
}
专用ICommand ResolveCommand()
{
ICommand命令=null;
if(this.Command!=null)
{
返回这个.命令;
}
if(base.AssociatedObject!=null)
{
foreach(base.AssociatedObject.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)中的PropertyInfo信息)
{
if(typeof(ICommand).IsAssignableFrom(info.PropertyType)&&string.Equals(info.Name,this.CommandName,StringComparison.Ordinal))
{
command=(ICommand)info.GetValue(base.AssociatedObject,null);
}
}
}
返回命令;
}
私有字符串命令名;
公共字符串命令名
{
得到
{
base.readPremission();
返回此.commandName;
}
设置
{
if(this.CommandName!=值)
{
base.writeStreamable();
this.commandName=值;
base.WritePostscript();
}
}
}
#地区司令部
公共ICommand命令
{
获取{return(ICommand)GetValue(CommandProperty);}
set{SetValue(CommandProperty,value);}
}
//使用DependencyProperty作为命令的后备存储。这将启用动画、样式、绑定等。。。
公共静态只读DependencyProperty CommandProperty=
Register(“命令”、typeof(ICommand)、typeof(InteractiveCommand)、new-UIPropertyMetadata(null));
#端区
}
与您从互联网上获取的任何代码一样,我强烈建议您通读整个课程,并尝试理解它的功能。不要把它扔进你的应用程序

现在我们可以做:

<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)
{
}
#带有事件参数的区域命令
DelegateCommand _CommandWithEventArgs;
/// 
///暴露。
/// 
带有EventArgs的公共DelegateCommand命令
{
获取{return{CommandWithEventArgs???({CommandWithEventArgs=new DelegateCommand(CommandWithEventArgs));}
}
#端区
带有事件参数的公共无效命令(MouseEventArgs参数)
{
}
这是一个总结;)

编辑:对于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
    }
公共类交互命令:TriggerAction
{
受保护的覆盖无效调用(对象参数)
{
if(base.AssociatedObject!=null)
{
ICommand命令=命令;
if((command!=null)&&command.CanExecute(参数))
{
command.Execute(参数);
}
}
}
#地区司令部
公共ICommand命令
{
获取{return(ICommand)GetValue(CommandProperty);}
set{SetValue(CommandProperty,value);}
}
//使用DependencyProperty作为命令的后备存储。这将启用动画、样式、绑定等。。。
公共静态只读DependencyProperty CommandProperty=
Register(“命令”、typeof(ICommand)、typeof(InteractiveCommand)、new-UIPropertyMetadata(null));
#端区
}

但请注意,它不如使用成熟的WPF版本安全(不检查类型,可能会因冻结的元素而崩溃)。

我尝试了InteractiveCommand,它给我带来了问题。相反,我设置了对Microsoft.Expression.Interactions和Include的引用

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

<i:Interaction.Triggers>
    <i:EventTrigger EventName="AppointmentEditing">
        <ei:CallMethodAction MethodName="AppointmentEditing" TargetObject="{Binding}" />
    </i:EventTrigger>
    <i:EventTrigger EventName="ShowDialog">
        <ei:CallMethodAction MethodName="ShowDialog" TargetObject="{Binding}" />
    </i:EventTrigger>
</i:Interaction.Triggers>

到目前为止效果良好。

不要在问题标题中添加标签。请参阅关于编写好标题的说明;)我认为这是非常灵活的开箱即用,这导致编写各种扩展来支持我们认为是基本的东西。只是尝试了你的代码,尽管我认为代码本身不起作用。(它是从更好的地方复制/粘贴的吗?)基本上CommandName从不被赋值,因此ResolveCommand返回null,因此整个操作都不起作用。还有一些小问题需要解决,比如base.WritePostscript();没有在基类中定义,但这并不重要。托克,请使用被证明有效的floowing代码段修改您的代码:,再次感谢您,祝您度过愉快的一天@bonomo我只在WPF中尝试过它,很高兴看到您可以将它移植到silverlight。@bonomo我把后面的代码弄乱了,我现在就修复了它。还有,我试过你的pas
    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
    }
xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" 

<i:Interaction.Triggers>
    <i:EventTrigger EventName="AppointmentEditing">
        <ei:CallMethodAction MethodName="AppointmentEditing" TargetObject="{Binding}" />
    </i:EventTrigger>
    <i:EventTrigger EventName="ShowDialog">
        <ei:CallMethodAction MethodName="ShowDialog" TargetObject="{Binding}" />
    </i:EventTrigger>
</i:Interaction.Triggers>
public void ShowDialog(object sender, ShowDialogEventArgs e) {

}

public void AppointmentEditing(object sender, AppointmentEditingEventArgs e) {

}