1

我正在使用AlexeyZakharov 的博客中的 InvokeDelegateCommandAction 类,这是基于一些人的建议,即这是将参数从 View 发送回 EventTrigger 的 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>

在视图模型中:

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....我在这里完全是个傻瓜吗?CommandParamter 在哪里链接到命令参数?AKA,为什么 View 没有将任何内容传递回命令?请帮忙。

4

2 回答 2

3

我用 aListBox代替了它,但我得到了同样的东西。以下很好,因为它传递CommandParameter而不是调用参数。那为什么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会传入一个SelectedItemCollectionfrom ListBox

您会很快发现另一个问题。DoSelectedActiveItemsChanged()'sparam将是 的实例SelectedItemCollection,而不是List<Object>

于 2011-06-20T15:40:50.960 回答
1

在乔尔的观察的帮助下,我已经解决了这个问题......对于那些可能感兴趣的人,这里是方法。尽管显然我正确地将正确答案归功于乔尔,但将这些信息作为答案而不是对问题的编辑似乎是正确的。

我发现了通用的 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 社区正在以最好和最丰富的方式让我越过学习曲线。

于 2011-06-21T10:30:51.113 回答