1

私はAlexeyZakharovのウェブログのクラスInvokeDelegateCommandActionを使用しています。これは、ViewからViewModelにEventTriggerからパラメータを送り返すための最良の方法であるという人々からのアドバイスに基づいています。

これが私が持っているものです。

ビュー(具体的には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;
    }
}

オブジェクトを引数として渡すことができる新しい種類の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に到達するときはいつでも、引数は常にNULLです....私はここで完全なバカですか?CommandParamterはどこでコマンド引数にリンクされますか?別名、ビューがコマンドに何も返さないのはなぜですか?助けてください。

4

2 に答える 2

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を渡します。SelectedItemCollectionListBox

もう1つ、すぐに気付く問題があります。は、ではなく、DoSelectedActiveItemsChanged()paramインスタンスになります。SelectedItemCollectionList<Object>

于 2011-06-20T15:40:50.960 に答える
1

私はジョエルの観察の助けを借りて問題を解決しました...興味があるかもしれない人のために、ここに方法があります。明らかに私はジョエルに正しい答えを正しく認めましたが、この情報を質問の編集ではなく答えとして置くのは正しいようです。

汎用のDelegateCommandを発見したので、DelegateCommandWithParameterを削除しました

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

'Do'(Executeメソッド)が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();
    }
} 

私のビジネスロジックの残りの部分と一緒に、それは非常にスムーズで直感的なUXになります。すべての回答者に感謝します。私はNHibernateでWPFとMVVMを1か月だけ行っていませんが、SOコミュニティが可能な限り最善かつ最も充実した方法で学習曲線を乗り越えていることを認めざるを得ません。

于 2011-06-21T10:30:51.113 に答える