#MVVMをFormsに適応してみる
##前置き
- GUIのアプリケーションを作るけど、いつも何か綺麗にコードがまとまらない
- 画面周りの処理のトラブルがよく発生する
ってことでそろそろちゃんとGUIのパタンを導入してみよう!
対象の環境は、「C# / Forms」
まずは名前がカッコ良いMVVMやってみよー!
##MVVMとは?
GUIを持つアプリケーションを実装するためのパターンである。
MVC(Model・View・Controller)の派生パターンで
MVVM(Model・View・ViewModel)というふうにクラス分けを行う。
WPFで採用されているのが一般的だと思われるが、
今回はFormsのソースに対応させてみる。
##MVVMがやりたいこと
- View(画面表示処理)とModel(画面表示以外のロジック処理)のコードを疎結合にしたい
- Viewはユニットテストしづらいため、極力Viewのコード量を減らしたい
##登場人物説明
Model
- アプリケーションを作ったきっかけである本来のやるべきこと(ドメイン:問題解決処理)を行う
- コマンドのこと?
例) 掲示板サーバと通信して、スレッド情報を取得したり、レスを書きこんだりする
View
- ViewModelを持つ
- ViewModelが持つプロパティを画面に表示する
- 画面のイベント(マウスクリックなど)からViewModelが持つコマンドを実行する
- コマンドを実行後、ViewModelが持っているデータが変化するため、画面更新する
例) スレッドビューワ・ボタンなどの配置を決め、ViewModelの処理結果を表示する
ViewModel
- いろいろなコマンドを持つ
- INotifyPropertyChangedを継承する
画面表示用データが変更されたらPropertyChangedEventArgsイベントを実行する
例) スレッド更新 / レス書き込みコマンドなど
操作のイベント(クリック、ショートカット入力)からコマンドを実行する
コマンド・・・ICommandインターフェイス(System.Windows.Input名前空間)を実装したクラス
System.Windows.Inputを使うため、「PresentationCore.dll」を参照に追加する
##FormsのDataBindの方法
webBrowser.DataBindings.Add("DocumentText", viewModel, "DocumentText");
コントロール.DataBindings.Add(コントロールのプロパティ名, viewModel, viewModelのプロパティ名);
##処理の流れ
View ⇒(メソッド呼び出し)⇒ ViewModel ⇒(メソッド呼び出し)⇒ ICommand.Executeを実行
ICommand ⇒ (NotifyPropertyChanged) ⇒ ViewModel ⇒ (NotifyPropertyChanged) ⇒ View(データバインドで画面の表示が変わる)
#実装してみた感想
##良かったこと
- この流れが結構綺麗にまとまっていてModel処理を切り離せられたのがよかった
View → ViewModel ⇔ Model
- ViewModelにプロパティと操作がまとまってるから、ユニットテスト組みやすそう
##良く分らなかったこと
- コマンド(Model)実行後の結果をどうやってViewModelに返すか良く分らなかったので、Model→ViewModel→View どちらともPropertyChangedで対応した
##ダメだったこと
- DataBindをWebBrowserに対して行うと、よく分らないタイミング(フォーカスがあたったタイミング?)でドキュメント更新されてしまう
あんまりDataBind信じれない - 結局、Viewが肥大化してしまった
→ DataBindが使いこなせないこともあって、「描画処理」をViewにゴリゴリかいてしまったことが原因
##参考ソース
実装してみたソース①
実装してみたソース② src\PeerstViewerフォルダが対象