ビューモデルとコマンドの関係、およびビューモデルの責任を理解するには、少し手助けが必要です。
私は例を挙げようと思います(Caliburn Microを使って)。
ビューモデルクラス、コマンドクラス、そして保存ボタン付きのビューがあります。
public class EditViewModel : Screen
{
public bool CanSave
{
get { return IsDirty; }
}
public void Save()
{
var command = new SaveCommand(this);//command gets reference to VM
command.Execute();
}
}
public class SaveCommand
{
private readonly EditViewModel _viewModel;
public SaveCommand(EditViewModel viewModel)
{
_viewModel = viewModel;
}
public void Execute()
{
var work = _viewModel.Work;
..
_viewModel.IsDirty = false;
}
}
ユーザーが「保存」をクリックしたとき。 Save()メソッドが呼び出され、作業内容を保存するコマンドが表示されます。
今私の質問は、コマンドはビューモデルへの参照を持っているべきですか?
いいえ)viewmodelはその作業をcommandに渡さなければなりません。そしてその保存結果をviewmodelに渡します。
Yes)コマンドはビューモデルへの参照を必要とし、プロパティはパブリックに設定可能である必要があります。
No seems like the cleanest way, but also requires extra work, when the work or result aren't a simple bool or similar.
根がすべてだと思います。ビューモデルとそのコマンド、ビューモデルの責任との関係は何ですか?
view-modelとそのコマンドの間には強い1:1の "friend"関係がありますか?ここでコードはちょうど他のクラスに移動されました。そのため、コマンドがビューモデルに直接アクセスすることに問題はありません。
もう1つの理解は、ビューモデルは非常に単純なクラスで、ほとんどプロパティがあり、ほとんどロジックが含まれていないことです。そのため、ロジックはコマンドに含まれているはずです。
あるいは、ビューモデルはかなりスマートで、アプリケーションロジックを含むべきです。 1つのビューモデル内にコマンドが多すぎる場合、またはコマンドコードがビューモデル内にとどまることがある場合は、コマンドが少し複雑になる場合にのみ、コマンドが本当に必要になります。
私はたぶん私が推測しているのですが、ビューモデルを理解するのを手伝ってください。
MVVMは、 Trygve Reenskaug で定義されている元のSmalltalk MVCパターンを直接継承しています。 MVCが非常に誤解されているように、MVVMも同様です。当初の定義では、MVCは、アプリケーションを駆動するデータとロジックを含む概念モデル(現在はドメインモデルと呼ぶ)、その概念モデルの視覚的表現を提供するView、および待機するControllerで構成されていました。ビュー上のイベントに追加し、それらをモデル内の操作として処理します。
人々が忘れているのは、Smalltalk環境が事実上最初に存在したGUIだったということです。これは、ゼロックスでの、まさしくJobsがLisaのために「エミュレート」した(そしてMicrosoftが後にWindowsのために活用した)プロジェクトです。 Smalltalkは、Win32 APIを直接プログラミングするのと同じように、非常に低レベルのユーザーインターフェースシステムを持っていました。コントローラは、メッセージポンプを監視し、UIに送信されたメッセージを論理的な操作に変換する役割を果たしました。 MVCパターンが最初に考案されたときは、ウィジェットライブラリはありませんでした。
数年前に進むと、Smalltalkはウィジェット付きの商用製品(VisualWorks)で、新しいパターンが登場しました。 MMVC 、これは2つのモデルを持つMVCです。また、アプリケーションモデルにとって重要な概念を含み、ドメインにとってではありません。
MMVCに関するC2 Wikiトピック(私の強調点)で興味深い点を指摘しましょう。
それで、あなたは言います。まあ、これは何ですか。一般原則のポイントとして、MVCアーキテクチャについて話す人々(J2EEやJSPコミュニティの人々など)は、WhatsaControllerAnywayについての混乱を避けるために、歴史的な意味と彼らが使用する用語の意味を理解するようにしてください。また、ModelViewControllerは、パラダイムの元のSmalltalk実装でModelModelViewControllerを意味することが多いことに注意してください。 実際には、「コントローラー」に割り当てられている責任の多く(Jacobsonianの意味での)は、ModelModelViewControllerアーキテクチャのApplicationModelに割り当てられている可能性があります。
MMVCアーキテクチャーは、通常コントローラーに割り当てられていたアプリケーションモデルの責務を与えました。 「私はボタンだ、誰かが私をクリックした」などのことを知っていたVisualWorksのウィジェットの導入のため。コントローラは、以前のように多くのロジックを含む必要はありませんでした。操作の派遣は、アプリケーションモデルに向かって、そしてコントローラーから離れて引き寄せられました。
MVVMは、個別のコントローラを持たないMMVCです。 ViewModelにはロジックを含める必要がありますが、コマンドを解釈してそれをさらなる処理のためにModelにディスパッチするのに十分なだけです。私が前に述べたように、Caliburnは慣例によりあなたのためにたくさんの配線をします。そのため、リレーコマンドを登録してメソッドに解決する代わりに、CaliburnはSaveという名前のViewModelメソッドを探し、Buttonに対してX:Name of Saveという名前で登録されたコマンドを関連付けます。 Saveメソッドに。
私はマイクブラウンが言ったことを言い換えるつもりです。
コマンドの主なポイントは、 DataContext
からボタンなどのアクティブコントロールへの簡単なデータバインドを可能にすることです。そこで、コマンドクラスを作成し、それをプロパティとして公開してボタンにバインドします。このボタンを押すとExecuteが呼び出されます。これは単にメソッドを直接バインドできないからです。また、実行されるものとして CanExecute
を一箇所に持つこともできます。
しかし、Caliburn.Microでは、規約を通じてメソッドを直接バインドできます。それは実際にあなたのために内部的にコマンドを作成します。したがって、Caliburn.Microでは、カスタムコマンドは実質的に不要です。
Caliburnは、コマンドターゲットへのコマンドとして、Autowire機能の「規約」を使用しています。そのため、ViewModelのSave機能は、裏側のコマンドにきちんとまとめられています(規約に関するCaliburnドキュメンテーションのアクションマッチング)。
caliburnは規則を使用してMVVMの儀式の一部を削除しているため、基本的に、コマンドの作成はまったくスキップできます。
MVVM Light Toolkit を使用したビューモデルクラスの例を示します。
public class EditViewModel : ViewModelBase
{
public EditViewModel()
{
SaveCommand = new RelayCommand(noParameter => Save());
}
private void Save()
{
//Save code goes here.
}
public static ICommand SaveCommand { get; private set; }
}
RelayCommand
クラスは、 SaveCommand
プロパティのすべての使用法をビューモデルクラスの Save()
メソッドに中継します。コマンド自体はビューモデルクラスのメンバーであるため、ビューモデルクラスを参照する必要はありません。