0

ICommand の Execute メソッドに渡されるパラメーターを変更する必要がありますか? そうでない場合、コマンドが呼び出された後にアプリケーションの状態またはビュー モデルを変更する最良の方法は何ですか?

考え

コマンド パターンは、オブジェクトのメソッドを呼び出します。WPF の場合は、モデルまたはビュー モデルです。これには、モデルが自分自身でアクションを実行する方法を知っている必要があります。私たちは皆、RelayCommand の実装を見て使用してきました。これに関する問題は、動作を交換するのが難しいことです。また、その「特殊なケース」のコードを配置する場所を見つけるのも困難です。別のビューを表示したい場合はどうすればよいですか?

ユースケースごとにコマンドを作成するというアイデアが気に入っています。ユース ケースを実行するためのロジックを処理する ICommand を実装する具象クラスを作成します。これには、コマンド パターンと同様にモデルへの参照が必要です。違いは、アクション ロジックがモデルの外部にあるため、パラメーターとして渡されたモデルを変更することです。サンプルコードを見てみましょう。

どこにでもある Person オブジェクトのリストを表示するウィンドウがあります。名前を消去するコマンドを Person で呼び出したいとします。MainViewModel には、People という Person オブジェクトのコレクションがあります。

 <Window.Resources>
    <commands:ClearNameCommand x:Key="ClearNameCommand"/>
</Window.Resources>
<Window.DataContext>
    <local:MainViewModel/>
</Window.DataContext>

これは、コレクションにバインドされたリスト ボックスで、名前をクリアするためのボタンで各人を表示します。

<ListBox ItemsSource="{Binding People}">
        <ListBox.ItemTemplate>
            <DataTemplate>
                <StackPanel Orientation="Horizontal">
                    <TextBlock Text="Name" Width="100"/>
                    <TextBox Text="{Binding Name}" Width="100"/>
                    <Button Command="{StaticResource ClearNameCommand}" CommandParameter="{Binding}" Content="Clear"/>
                </StackPanel>
            </DataTemplate>
        </ListBox.ItemTemplate>
    </ListBox>

以下は、具象クラス ClearNameCommand の Execute メソッドです。アクションを実行するかどうかを尋ねるダイアログ ボックスが表示されます。これは、モデルにこのコマンドを入れない理由の良い例だと思います。また、名前が消去されたことをどこかに記録する必要があると想像してみてください。元に戻す やり直すかも?? このコードはどこに行くのですか??!!

public void Execute(object parameter)
    {
        Person p = parameter as Person;
        if (p != null)
        {
            if (MessageBox.Show(
                "Are you sure you want to clear the name?", 
                "Clear Name", 
                MessageBoxButton.YesNo, 
                MessageBoxImage.Question) == MessageBoxResult.Yes)
            {
                p.Name = "";
            }
        }
    }

すべての準備コードをコマンドに残してから、Person で Clear メソッドを呼び出すことができると思います。ただし、それが最善の方法であるとはまだ確信していません。クリアが変わったら?Clear2 と Clear3 などになります。考えられるすべてのユースケース、またはそれ以上のユースケースの方法は言うまでもありません。

いくつかのより多くの考え

したがって、パススルー データ バインディングを許可するモデルへの参照を持つビュー モデルがあるとします。または、モデルをすべてまとめてラップします。私が回避したいのは、単一のユース ケースごとに View Model に Command プロパティを作成することです。また、そのデザインの何がそんなにきれいなのですか?Execute メソッドで Model オブジェクトを変更しています。コマンドパターンをそれほど曲げているとは思いません。私のウィンドウはクライアントです。モデルはレシーバーです。そしてボタンはインボーカーです。唯一の違いは、呼び出し側で依存関係を注入していることです。

私の質問を少し言い換えると、これを行うための赤い旗を見ている人はいますか?

コマンドパターンを調べているときにこれを見つけました。 http://msdn.microsoft.com/en-us/library/cc984279.aspx

4

1 に答える 1

0

何を言っているのかさっぱり分からない... あなたはとても... ええと、ユニークな方法で仕事をしているようですねCommand

これには、モデルが自分自身でアクションを実行する方法を知っている必要があります。

モデル クラスにCommands を含めることはできません...代わりに、そのモデル クラスを表示するビュー モデルに配置します。

... 行動を入れ替えるのは難しい

また…何?「行動を交換」しないでください。Commandはその機能を変更すべきではありません。関数ごとに 1 つ作成するだけです。

その「特別なケース」のコードを配置する場所を見つけることも困難です

「特殊ケース」コードとは何ですか?

別のビューを表示したい場合はどうすればよいですか?

各ビューには独自のビュー モデルが必要です。各ビュー モデルには、独自のICommandオブジェクト セットが必要です。Lambdaで小さな式を複製する必要がある場合は、実際には問題ありませんRelayCommand

名前が消去されたことをどこかに記録する必要があると想像してみてください。元に戻す やり直すかも?? このコードはどこに行くのですか??!!

ビュー モデル、ビュー モデル、ビュー モデル。

すべての準備コードをコマンドに残してから、Person で Clear メソッドを呼び出すことができると思います

p.Name = ""同じことをした呼び出しと呼び出しの違いは何だと思いますp.ClearName()か? 違いはありません。プロパティを直接設定するよりも、メソッドを呼び出す方がわずかに時間がかかります。

クリアが変わったら?最終的に Clear2 と Clear3 などになります。

もう一度…何???どのようにName = ""変化しますか?

あなたの質問のいくつかに答えたことを願っていますが、私はあなたの質問を完全には理解していないので、何らかの形であなたを誤解したに違いないと思います. さらに質問をしてください。ただし、質問に編集として追加してください。コメントが途方もなく長くならないように、この回答で返信します。


更新 >>>

最初の 2 つのコメントへの対応:

はい...ほとんどの場合、1 つのビュー モデルに対して 1 つのビューを使用します。いいえ、 a から何かの値を変更することにまったく問題はありませんCommand。それが良くないとあなたが考える理由は思いつきません。次のシナリオを想像してください。

オブジェクトのリストと、ユーザーがオブジェクトを編集するために使用できる UI の編集パネルがあります。という名前の aButtonを持つもあります。さて、定義上、それは、データ オブジェクト、またはモデル クラスと呼ぶと「変化」します。CommandDuplicateCommand

新しいオブジェクトを作成し、現在選択されているオブジェクトの値に応じてそのプロパティを設定します。Commandこれを行うには何らかの形でこれが間違っていることを示唆していますか? 私の意見では、Command(またはメソッド) 機能の大部分は、ビュー内のデータ オブジェクトの一部のプロパティを「変更」します...この便利な機能を他にどのように提供しますか?

そして、「これはどこにあるべきか?」に進みます。質問...他にどこにありますか?ビュー モデルでは、現在選択されているアイテムとアイテムのコレクション全体にアクセスできます。ビュー モデルから、あらゆる種類の機能を提供する任意の数のサービスにアクセスできます。Command別々のクラスからこれらのもののいくつかに接続するのは難しいと思うでしょう.

于 2013-11-13T16:18:35.027 に答える