Edited at

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

More than 1 year has passed since last update.


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