使用InvokeDelegateCommandAction触发事件的CommandParameter

时间:2011-06-20 14:09:04

标签: wpf mvvm datagrid readonly delegatecommand

我正在使用来自AlexeyZakharov's weblog的类InvokeDelegateCommandAction,根据人们的一些建议,这是从EventTrigger将View中的参数发送回ViewModel的最佳方法。

这就是我所拥有的。

在视图中(特定的DataGrid):

<i:Interaction.Triggers>
    <i:EventTrigger EventName="SelectionChanged" >
        <cmnwin:InvokeDelegateCommandAction 
                Command="{Binding SelectedExcludedItemChangedCommand}"
                CommandParameter="{Binding RelativeSource={RelativeSource self}, Path=SelectedItems}" />
    </i:EventTrigger>
</i:Interaction.Triggers>

在ViewModel中:

public DelegateCommandWithParameter SelectedActiveItemChangedCommand
{
    get
    {
        return selectedActiveItemChangedCommand ??
            (selectedActiveItemChangedCommand = new DelegateCommandWithParameter(DoSelectedActiveItemsChanged, CanDoSelectedActiveItemsChanged));
    }
}

public bool CanDoSelectedActiveItemsChanged(object param)
{
    return true;
}

public void DoSelectedActiveItemsChanged(object param)
{
    if (param != null && param is List<Object>)
    {
        var List = param as List<Object>;
        MyLocalField = List;
    }
}

允许我以args传递对象的新类型DelegateCommand:

public class DelegateCommandWithParameter : ICommand
{
    #region Private Fields
    private Func<object, bool> canExecute;
    private Action<object> executeAction;
    private bool canExecuteCache;
    #endregion

    #region Constructor
    public DelegateCommandWithParameter(Action<object> executeAction, Func<object, bool> canExecute)
    {
        this.executeAction = executeAction;
        this.canExecute = canExecute;
    }
    #endregion

    #region ICommand Members
    public bool CanExecute(object parameter)
    {
        bool temp = canExecute(parameter);
        if (canExecuteCache != temp)
        {
            canExecuteCache = temp;
            if (CanExecuteChanged != null)
            {
                CanExecuteChanged(this, new EventArgs());
            }
        }
        return canExecuteCache;
    }

    public event EventHandler CanExecuteChanged;

    public void Execute(object parameter)
    {
        executeAction(parameter);
    }
    #endregion
}

每当我的代码到达DoSelectedActiveItemsChanged时,arg总是为NULL ....我在这里是一个完整的doofus吗? CommandParamter在哪里链接到命令args? AKA,为什么视图没有回复命令?请帮忙。

2 个答案:

答案 0 :(得分:3)

我用ListBox代替了它,但我得到了相同的东西。以下情况很好,因为它传递CommandParameter而不是invoke参数。那么为什么CommandParameter null

protected override void Invoke( object parameter ) {
    this.InvokeParameter = parameter;

    if ( this.AssociatedObject != null ) {
        ICommand command = this.ResolveCommand();
        if ( ( command != null ) && command.CanExecute( this.CommandParameter ) ) {
            command.Execute( this.CommandParameter );
        }
    }
}

CommandParameter似乎无法正常工作,因为您的绑定将其设置为null{RelativeSource Self}解析为InvokeDelegateCommandAction,但没有SelectedItems属性。相反,使用此绑定:

CommandParameter="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBox}}, Path=SelectedItems}"

然后CommandParameter将从SelectedItemCollection传入ListBox

还有一个问题,你很快就会发现。 DoSelectedActiveItemsChanged()的{​​{1}}将是param的实例,而不是SelectedItemCollection

答案 1 :(得分:1)

我已经借助乔尔的观察解决了这个问题......对于那些可能感兴趣的人来说,这是怎么回事。虽然显然我已经将Joel正确地归功于正确答案,但将这些信息作为答案而不是编辑问题似乎是正确的。

我发现了通用的DelegateCommand,所以摆脱了DelegateCommandWithParameter

public ICommand SelectedObjectsChangedCommand 
{
    get
    {
        return selectedObjectsChangedCommand ??
            (selectedObjectsChangedCommand = new DelegateCommand<MyType>(DoSelectedObjectsChangedCommand , CanDoSelectedObjectsChangedCommand ));
    }
}

'Do'(执行方法)现在返回SelectionChangedEventArgs ...

public void DoSelectedObjectsChangedCommand(object param)
{
    if (param != null && param is SelectionChangedEventArgs)
    {
        foreach (MyType object in ((SelectionChangedEventArgs)param).AddedItems.Cast<MyType>().ToList())
        {
            selectedObjects.Add(object);
        }
        foreach (MyType object in ((SelectionChangedEventArgs)param).RemovedItems.Cast<MyType>().ToList())
        {
            selectedObjects.Remove(object);
        }
        UpdateAllCanDos();
    }
} 

除了我的其他业务逻辑外,它还可以实现非常流畅和直观的用户体验。非常感谢所有答案者。我一直用NHibernate做WPF和MVVM只用了一个月而且我不禁承认SO社区正在以最好和最丰富的方式让我学习学习曲线。