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