WPF MVVM初心者がみたMVVMライブラリが提供するもの

WPFといえばMVVM。ただWPFのMVVMは補助ライブラリがないと開発がキツイなどと言われます。何がどうキツイのか、ライブラリが何を提供してくれるのかを学習してみました、初心者の私がこれを読む初心者の方にわかるよう説明してみたいと思います。

補助ライブラリとしては、MVVM Light toolkit, Composite Application Guidance for WPF(旧PRISM), Livet が有名です。MVVM Light toolkitは非常に多くダウンロードされているという噂、Composite Application Guidance for WPFはLightToolKitに比べてパフォーマンスが良くないという噂、Livetは国産のMVVMライブラリで細部のサポートが行き届いたライブラリという噂みたいです。

0.ライブラリについて

今回の目的はこれらライブラリが何を目的としているかを探ることなので、どれでもいいのですがひとまずMVVM Light toolkit を使ってみます。ダウンロードしてきてインストールします、何も考えずインストール/Ok連打で問題なし。

install_mvvmtoolkit

VS2010proではダメだったのですが、VS2013proではプロジェクトテンプレートがインストールされるようです。

vs2013_project_mvvmlight

プロジェクトを開くとUnityをDIコンテナとして使っていたりする様子がわかります。多分このテンプレートを使ってサンプルMVVMとして作られたApunta Notasというソフトがあります。ダウンロードしてこのソースコードを読んでみると、app.xamlにViewModelをリソースで登録しておくことで各ウィンドウでそれが参照できるんだなとか、きれいなレイアウトはこうやって作ってるんだな、とか色々学ぶことがあります。

 

1.MVVMのキソ

私が知ったかぶりをして下手な説明をするより、この上なくわかりやすく説明されている方がいらっしゃるのでそちらをご紹介します。とはいえLinkを読まずに本エントリの下記の内容がわかるレベルでMVVMを私なりに説明してみると、、

wpf_mvvm_image

こんな感じかと。注意頂きたいのはWPFはModelに関与せず、ViewModelとViewの部分に関与します。WPF用のMVVMライブラリもViewModelとViewへのサポートがメインです。また、Viewは表示データの管理には携わらないことも重要です。まずこれを頭にいれておいてください。

 

2.ライブラリで提供されるもの

ライブラリを覗くと、Messenger、ビヘイビア、RelayCommandと見慣れないものに気付きます。他にも色々ありますが、これらが今回説明してみようとしているものです。

①ViewModelBase

WPFは華やかなUIという一面ももちますが、MVVMを意識した数多くの機能があります。バインディングもその一つ、以前本ブログで単項データバインディングついて説明しました。INotifyPropertyChangedでデータ更新を通知するんでした。INotifyPropertyChangedにはPropertyChangedイベントがありますが、プロパティのSetterでイベント発砲するのは同じなのでこれを簡略化することが可能です。

Collectionの場合はINotifyCollectionChangedというインターフェースに対してObservableCollectionという クラスがあるのですがINotifyPropertyChangedに対応するものがありませんのでライブラリではこれを提供しています。またViewModelは必ずINotifyPropertyChangedを実装するハズなのでこれを継承したViewModelBaseというものもライブラリが提供します。MVVMで作った場合のViewModelはこのViewModelBaseから派生するのが良いでしょう。

viewmodelの基底

 

②RelayCommand

WPFが規定するのはViewModelとViewの関係であることは上の通りです、基本的にBindingとINotifyPropertyChangedインターフェースによりデータの同期を保ちます。しかし、Viewにはコントロールがありそれを操作したら**するというイベントドリブン的な構造は必要不可欠です。

しかし、イベントハンドラをあちこちに定義すると優れたMVVMからどんどん遠ざかっていきます。DRY違反懸念もありますが、一番気にすべきは責務分離不十分の問題です。ボタンをダブルクリックするなどしてイベントハンドラを定義した場合Window.xaml.csというViewの裏処理であるコードビハインドにロジックを書くことになります。これだとViewが表示以外の責任を持ってしまうのでイベントハンドラでもViewModelに書くべきです。

これを解決するWPF標準の方法はコマンド(ICommandを実装したもの)をViewModelに定義し、それをViewが参照+実行する方法です。

viewmodel_view_command

ただ単純な処理を実行したいのにコマンドを定義するのは面倒なときにRelayCommandがあります。FuncやActionデリゲートをコンストラクタに指定することでICommandインターフェースを実装したViewにバインドできるCommandオブジェクトを作成することができるのです。

『えっ、イベントハンドラをコードビハインドに定義するとMVVMじゃなくなるの?』という質問に対する答えは、厳密にはYES(=MVVMを崩壊させうる)です。そのためにイベントハンドラにコマンドをアタッチするという方法を取ってViewModelに処理をまとめるのがよさそうです。

 

③Messenger, ビヘイビア

ViewModelはViewを参照しません。しかし例えばViewModelは表示データの設定整合なども担うので勝手に調整してよいか、変更をキャンセルするかなどユーザに問い合わせるケースも必要です。しかしViewModelはViewを参照してはならないので、ViewModelからViewへ通知する仕組みが必要です。その一つがMessengerです(他の方法もあります)。

ViewはMessengerによびだされた場合の処理(コールバック、イベントハンドラと同義)を登録しておき、ViewModelが所望のタイミングでMessengerに操作開始を通達することで実現しています。ViewModelからViewを参照する矢印がないことが重要なポイントです。

viewmode_view_messenger

またViewの表示やユーザーインタラクションの部分だけを切り出したものがビヘイビアです。

とまぁ浅い知識かもしれませんが、全体図とだいたい上の内容が頭に入っていると理解しやすいかと思います。MFC時代のDoc-Viewアーキテクチャがどうもしっくりこなかった私にMVVMは強く響く存在になっています。

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中