GUIアプリケーションの設計:MVVMについて


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」を参照に追加する

参考・・・第6回 「コマンド」と「MVVMパターン」

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フォルダが対象