.NET開発者中心 厳選ブログ記事

MVVMパターンの常識 ― 「M」「V」「VM」の役割とは?

尾上 雅則
2011/05/18

View

 XAMLで記述され、UIの外観と構造を定義します。基本UIのコードビハインドには、初期のInitializeComponentメソッド以外何も記述されているべきではありません。これについては、『Prism開発ガイド』に以下のような記述があります。

「Prism Development Guide Chapter 5: Implementing the MVVM Pattern」の「The View Class」より引用】:

 ViewのコードビハインドにはIntializeComponentメソッドを呼び出すコンストラクタだけが含まれているのが理想的です。しかし、複雑に組み合わされたアニメーションや、Viewの一部の要素を直接操作する必要のある場面があった場合のように、視覚的な動作を実装するのに、XAML(Extensible Application Markup Language)で実現するのが難しいか、あるいは非効率な場面もあります。そういった場合は、コードビハインドにUIロジックが含めざるを得ないこともあります。自動単体テストをしたいのなら、コードビハインドに安易にロジックを置きすぎてはいけません。通常、Viewのコードビハインドのロジックをテストするには、UIオートメーションによるテストを行います。

(原文:Ideally, the code-behind of a view contains only a constructor that calls the InitializeComponent method. In some cases, the code-behind may contain UI logic code that implements visual behavior that is difficult or inefficient to express in Extensible Application Markup Language (XAML), such as complex animations, or when the code needs to directly manipulate visual elements that are part of the view. You should not put any logic code in the view that you need to unit test. Typically, logic code in the view’s code-behind will be tested via a UI automation testing approach.)

 アニメーションなどが複雑に絡み合った処理では、コードビハインドが必須になるパターンもあるらしいです(わたしがまだ出会ったことがない程度にはレアケースです)。しかしそれはいずれにせよView内にとどめるべき処理で、ViewModelとコードビハインドを通じて対話してはいけません。

コードビハインドを書かないメリット

 コードビハインドを書かないことで何のメリットがあるかといえば、それはパターンの崩壊を防ぎやすい点が1つ挙げられます。

 もともとアプリケーション全体にまたがる設計パターンは、管理パターンでもあります。きちんと管理できているなら、スパゲティ・コードでも何ら問題はないのです。人間はきちんと管理できないので(あるいは大きなコストがかかり過ぎるので)、設計パターンを使用して管理を単純化します。

 コードビハインドを使用しないということは、下位レイヤをコードで触る手段がない(というか非常に困難)ということです。責務が責務の範囲を飛び出すことが阻止されます。また、ViewとViewModelの通信手段をデータ・バインドだけに統一するために、コードビハインドを使用しないことは大きな影響を与えます。

 コードビハインドを使用しないもう1つのメリットは、Viewを宣言的構文であるXAMLコードだけで記述できるという点です。宣言的構文は、WYSIWYGなHTMLエディタなどを見ても分かるとおり、プログラミング言語の知識がなくとも、ツールの支援を受けやすい点がメリットです。

 もともとUIを妥協したくないからこその、WPF/Silverlight。この特徴は非常に重要なポイントです。

 後述する、ビヘイビア、トリガー、アクションを駆使することで、コードビハインド無しでViewを作成することが可能になります。

ViewModelとの対話 ― データ・バインディング

 Viewは、データ・バインディング機構を使ってViewModelの各プロパティの値を表示します。通常、ViewのDataContextプロパティにViewModelのインスタンスを設定することで、ViewはViewModelとバインドします。ViewからViewModelの情報を取得するのは、内部的にはリフレクションや各種Descriptor(=TypeDescriptionProviderクラスなど)で行われています。ViewModelからの変更通知イベントを受け取ることで、Viewの値は更新されます。

 WPF/Silverlightのデータ・バインディングは、双方向のデータ・バインディングに対応しています。ユーザー入力をViewModelに伝播(でんぱ)させることもできます。

 ダイアログの表示や、画面遷移の指示などの、ViewModelのプロパティとして表現されるべきでない情報は、ViewにバインドされたViewModelのMessengerからメッセージ・イベントを受け取ることでViewのメッセージ・トリガーが処理します。

 大事なことはメッセージ・イベントを受け取ってダイアログや画面遷移を行うことは、データ・バインディング機構の考え方と酷似している、あるいはほとんど同一であることをきちんと認識することです。Messengerについては詳しく後述します。

 ViewはViewModelとの対話をすべてデータ・バインディングで処理します。これがMVVMパターンをいまの形ならしめている最も大きなファクタだといっても過言ではありません。

ビヘイビア、トリガー、アクション

 XAMLだけでは足りない機能は、別途、ビヘイビア、トリガー、アクションを作成して対処します。ビヘイビア、トリガー、アクションを使用すれば、コードビハインドで実現したかった要件はほぼすべて満たせます。

 ビヘイビアというのは、特定のコントロールのコードビハインドをXAMLコードで再利用可能なように外出ししたものです。ViewModelとの通信などは行いません。あるコントロールの宣言に外部からアタッチできるWPFのプロパティ・システムの特徴を使って実現されています。コマンドに対応していないコントロールをコマンドに対応させるビヘイビアや、オブジェクトの移動に自動的にきれいなアニメーションを与えるビヘイビアなど、多種多様なものがあります。

 トリガーは、任意の条件で起動してアクションを実行するためのものです。ViewModelのプロパティの変化を検知して起動するトリガーや、タイマーなトリガー、イベント・トリガー、ViewModelからメッセージを受け取って起動するトリガーなど、いろいろあります。

 アクションは、トリガーとセットで使われるアクションです。ダイアログを表示したり、特定のストーリーボードを起動したり、ViewModelのプロパティに値をセットしたり、はたまた画面遷移したり、いろいろできます。

 トリガーとアクションについては、Expression Blend SDK(WPF版)同(Siliverlight版)や各種MVVMインフラストラクチャ(例えばLivetMVVM Light Toolkit, Prism)で用意されているもので対応するのが望ましいです。いちいち自分で作らなくても、ビジネス・ドメインに結合したものじゃないので、用意されてあるものを使うに越したことはありません。

 ビヘイビアもトリガーもアクションも、作成はC#などの汎用プログラミング言語で行いますが、使用する際はXAMLコードの既存のコントロールの適切なプロパティに設定するだけです。

 ビヘイビアも、トリガーも、アクションも、Expression Blend SDKや各種MVVMインフラを使用しないと、ほとんど標準で用意されていないうえに、標準で用意されているもの利用用途が非常に限定的で実用できるようなものではないので注意が必要です。

 Expression Blend SDKは絶対に必須です。その上に何らかのMVVMインフラの助けが必要でしょう。

 なお、Expression Blend SDKはExpression Blendを持っていなくてもダウンロード・使用が可能で、再配布可能なアセンブリを含みます。

 ビヘイビア、トリガー、アクションの詳細については以下の記事をどうぞ。

 続いてViewModelを説明します。


 INDEX
  .NET開発者中心 厳選ブログ記事
  MVVMパターンの常識 ― 「M」「V」「VM」の役割とは?
    1.MVVMパターン概要
  2.View
    3.ViewModel
    4.Model
    5.デザイナーと開発者の分業/MVVMパターンを適用・カスタマイズするときの留意点

インデックス・ページヘ  「.NET開発者中心 厳選ブログ記事」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)
- PR -

注目のテーマ

業務アプリInsider 記事ランキング

本日 月間
ソリューションFLASH