MVPVMパターン

えムナウ (児玉宏之)
http://mnow.jp/
http://mnow.wankuma.com/
http://blogs.wankuma.com/mnow/
http://www.ailight.jp/blog/mnow/
アジェンダ

•   はじめに
•   MVPVM 設計パターン
•   ナビゲーション
•   プレゼンター
•   まとめ
はじめに

• MSDN マガジン2011年12月号で発表され
  た「MVPVM 設計パターン」ですが、私も
  ViewとViewMode​lの両方を知っていて現状
  の画面状態を管理する何者かが​必要なこと
  は感じていました。
• Applicationの派生クラスやApplicat​ionが操
  作するオブジェクトとして現状の画面状態
  を管​理やナビゲーションをする機能をつ
  くっていました。今回のセッションでは私
  なりに研究した「MVPVM 設計パターン」
  をお届けします。
MVPVM 設計パターン

• モデル - ビュー - プレゼンター - ビューモ
  デル (MVPVM: Model-View-Presenter-
  ViewModel) パターンは、 Microsoft
  patterns & practices の Prism プロジェク
  トで導入されました。
• MVVM の能力と機能をすべて利用でき、
  MVPの拡張性からプレゼンテーションロ
  ジックの複雑さにも対応でき、ViewModel
  は本来あるべきプロパティ公開とコマンド
  の受付になります。
MVPVM 設計パターン

• MVPVMパターン
 – それではMVPVMパターンとはなんでしょう
   か?
 – MVVMパターン と MVPパターンを合体させた
   ものです。
 – MVVMパターン と MVPパターンを見てみま
   しょう。
MVPVM 設計パターン

• MVVMパターン
 – View:ユーザーインターフェースの外観や配
   置や反応(インタラクション)を定義する
 – ViewModel:Viewの必要な情報をプロパティ
   で公開しユーザー入力やコマンドを処理する
 – Model:データの取得や管理を行いプログラム
   の処理の中核となる
MVPVM 設計パターン

• MVVMパターン


   View                          Model



                コマンド
データバ
インド


                ViewModel
          プロパ               データ取得・更
          ティ                新
MVPVM 設計パターン

• MVPパターン
 – View:ユーザーインターフェースの外観や配
   置や反応(インタラクション)を定義する
 – Presenter:Viewのナビゲーションを管理し
   ユーザー入力をModelに伝える
 – Model:データの取得や管理を行いプログラム
   の処理の中核となる
MVPVM 設計パターン

• MVPパターン


   View                        Model



              入力




              Presenter
     ナビゲーショ               データ取得・更
     ン                    新
MVPVM 設計パターン

• MVPVMパターン
 – View:ユーザーインターフェースの外観や配
   置や反応(インタラクション)を定義する
 – ViewModel:Viewの必要な情報をプロパティ
   で公開しユーザー入力やコマンドをPresenter
   に渡す
 – Presenter:ViewやのViewModelのナビゲー
   ションを管理しユーザー入力をModelに伝える
 – Model:データの取得や管理を行いプログラム
   の処理の中核となる
MVPVM 設計パターン

• MVPVMパターン

                                Presenter
                   ナビゲーショ
   View            ン                    データ取得・更
                                        新

            コマンド
データバ                           データ更新依頼
インド


                   ViewModel
          プロパ                               Model
          ティ
ナビゲーション

• ナビゲーション
 – MVVMパターンではどこがナビゲーションを
   担当していたのでしょうか?
 – 答えの一つはメッセージ+ビヘイビアーです。
 – ビヘイビアーはViewの分類になります。
 – 「ViewModel から View を操作する」という
   こと葉を聞いたことがある人もいるでしょ
   う。
 – 操作というのはメッセージを送ってメッセー
   ジボックスやダイアログを表示したりするこ
   とも多かったのです。
ナビゲーション
  • メッセージボックス
public class DialogMessageBehavior : Behavior<DependencyObject>
  {
     protected override void OnAttached()
     {
        base.OnAttached();
        Messenger.Default.Register<DialogMessage>(AssociatedObject, p => Invoke(p));
     }
     protected override void OnDetaching()
     {
        base.OnDetaching();
        Messenger.Default.Unregister<DialogMessage>(AssociatedObject);
     }
     private void Invoke(object parameter)
     {
        DialogMessage message = parameter as DialogMessage;
         MessageBoxResult result =
MessageBox.Show(message.Content, message.Caption, message.Button, message.Icon, m
essage.DefaultResult, message.Options);
         message.ProcessCallback(result);
      }
  }
ナビゲーション
  • ダイアログ
public class DialogMessageBehavior : Behavior<Wndow>
  {
     protected override void OnAttached()
     {
        base.OnAttached();
        Messenger.Default.Register<DialogMessage>(AssociatedObject, p => Invoke(p));
     }
     protected override void OnDetaching()
     {
        base.OnDetaching();
        Messenger.Default.Unregister<DialogMessage>(AssociatedObject);
     }
     private void Invoke(object parameter)
     {
        DialogMessage message = parameter as DialogMessage;
         AssociatedObject.DataContext = message.ViewModel;
         bool? result = AssociatedObject.ShowDialog();
         message.ProcessCallback(result);
      }
  }
ナビゲーション

• ナビゲーション
  – MVVMパターンでは他にどこがナビゲーショ
    ンを担当していたのでしょうか?
  – 答えの一つはViewModel+DataTemplateです。
<DataTemplate DataType="{x:Type c:GreekGodViewModel}">
    <TextBlock Text="{Binding Path=Name}" Foreground="Gold"/>
</DataTemplate>


  – さらに DataTemplate をデータによって切り
    替える DataTemplateSelector というのもあり
    ます。
  – DataTemplate はViewの分類になります。
ナビゲーション

 • DataTemplateSelector
public class TaskListDataTemplateSelector : DataTemplateSelector
{
  public override DataTemplate
         SelectTemplate(object item, DependencyObject container)
  {
     FrameworkElement element = container as FrameworkElement;
     if (element != null && item != null && item is TaskViewModel)
     {
         var taskitem = item as TaskViewModel;
         if (taskitem.Priority == 1)
             return element.FindResource("importantTaskTemplate") as DataTemplate;
         else
             return element.FindResource("myTaskTemplate") as DataTemplate;
     }
     return null;
  }
}
ナビゲーション

• MVVMパターンは、View と ViewModel は
  疎結合でお互いに交換可能であるというこ
  とが利点の一つであるといわれていまし
  た。
• どうして今見てきたような密結合が生まれ
  てしまったのでしょうか?
• ナビゲーションは View と ViewModel の両
  方を知らないとできません、この場合
  View に仕込んでますので ViewModel や 本
  来ViewModel にあるべきデータが View に
  出てきてしまいます。
ナビゲーション

• ナビゲーション
 – MVVMパターンではViewだけがナビゲーショ
   ンを担当していたのでしょうか?
 – 答えの一つはアプリケーションクラスです。
 – アプリケーションクラスはMVVMパターンの
   範囲外です。
 – 範囲外であれば別に問題ないのでしょうか?
 – ナビゲーションを担当する Presenter があれ
   ばアプリケーションクラスはすっきりするは
   ずです。
ナビゲーション
• アプリケーションクラス
protected override void OnStartup(StartupEventArgs e)
     {
       var win = new Views.TwitterWindow();
       this.MainWindow = win;
       var account = LoadAccount();
            if (account == null)
           account = NewAccountWithDialog();
       if (account != null)
           SaveAccount(account);
       else
       {
           MessageBox.Show("認証失敗");
           return;
       }
       var vm = new ViewModel.TwitterViewModel(
                    ConsumerKey, ConsumerSecret, account.Token);
       win.DataContext = vm;
       win.Show();
       base.OnStartup(e);
     }
プレゼンター

• プレゼンターの役割
 – View と ViewModel のインスタンス作成を行
   います。
 – View をパネルなどのコンテナに追加し、
   DataContext に ViewModel をセットします。
 – Model に表示すべきデータを要求し
   ViewModel にセットします。
 – 上位の Presenter や ViewModel の依頼により
   更新すべきデータを収集し Model を更新しま
   す。
 – View と ViewModel のインスタンス解放を行
   います。
プレゼンター

• プレゼンターの構成
 – Presenter はパネルなどのコンテナで複数の
   Presenter を管理する Presenter と、ユーザー
   コントロールやダイアログなどの単一ビュー
   を管理するPresenter があります。
 – View や ViewModel が階層構造になっている
   ように Presenter も階層構造になります。
プレゼンター

• プレゼンターの利点
 – Application や ViewModel からプレゼンテー
   ションロジックを解放します。
 – View と ViewModel は疎結合でお互いに交換
   可能な状態に戻すことにより、再利用性を高
   め View や ViewModel をライブラリ化しやす
   くします。
 – View と ViewModel と Model 全てにアクセス
   可能な存在なので、アンドゥ・リドゥの実装
   場所に最適です。
 – ViewModel から View をクローズするメッ
   セージは必要なくなります。
プレゼンター

• 親が子供を管理
 – ダイアログ を表示させたいPresenterは ダイ
   アログを管理するPresenterを生成して、ダイ
   アログが閉じたら解放します。
 – パネルなどのコンテナを管理するPresenterは、
   パネルの中身を管理するPresenterをパネル内
   に表示するときに生成してパネルから削除さ
   れるときに解放します。
プレゼンター

• コンテナ内をスライドして入れ替わる




        A画面      B画面
プレゼンター

• WPFやSilverlightではこんな画面変化も可
  能ですが、この場合はコンテナとなるパネ
  ルにストーリーボードを仕掛けて
  RenderTransform の TranslateTransform
  を変化させて表示を変えます。
• 最初にA画面とB画面の View と
  ViewModel を用意してA画面を表示範囲内
  にB画面を表示範囲外に設定してストー
  リーボードを起動します。
プレゼンター

• MVVMパターンでは、 A画面とB画面の
  View と ViewModel を知っている何かの存
  在が必要でコンテナの View で実行すると
  したら、かなりの密結合になってしまった
  と思います。
プレゼンター

• MVPVMパターンでは、 A画面のPresenter
  はA画面の View と ViewModel を知ってい
  て、 B画面のPresenterはB画面の View と
  ViewModel を知っています、コンテナの
  Presenterはコンテナの View と
  ViewModel の他に、 A画面とB画面の
  Presenterを知っています。
• 役割分担でき疎結合性も保たれます。
まとめ

• MVPVMパターンはMVVM の能力と機能を
  すべて利用でき、 MVPの拡張性からプレ
  ゼンテーションロジックの複雑さにも対応
  できます。
• MVPVMパターンは View と ViewModel は
  疎結合でお互いに交換可能な状態に戻すの
  に有効な手段です。
• 皆さんも検討してみたらどうでしょうか?

Mvpvm pattern

  • 1.
  • 2.
    アジェンダ • はじめに • MVPVM 設計パターン • ナビゲーション • プレゼンター • まとめ
  • 3.
    はじめに • MSDN マガジン2011年12月号で発表され た「MVPVM 設計パターン」ですが、私も ViewとViewMode​lの両方を知っていて現状 の画面状態を管理する何者かが​必要なこと は感じていました。 • Applicationの派生クラスやApplicat​ionが操 作するオブジェクトとして現状の画面状態 を管​理やナビゲーションをする機能をつ くっていました。今回のセッションでは私 なりに研究した「MVPVM 設計パターン」 をお届けします。
  • 4.
    MVPVM 設計パターン • モデル- ビュー - プレゼンター - ビューモ デル (MVPVM: Model-View-Presenter- ViewModel) パターンは、 Microsoft patterns & practices の Prism プロジェク トで導入されました。 • MVVM の能力と機能をすべて利用でき、 MVPの拡張性からプレゼンテーションロ ジックの複雑さにも対応でき、ViewModel は本来あるべきプロパティ公開とコマンド の受付になります。
  • 5.
    MVPVM 設計パターン • MVPVMパターン – それではMVPVMパターンとはなんでしょう か? – MVVMパターン と MVPパターンを合体させた ものです。 – MVVMパターン と MVPパターンを見てみま しょう。
  • 6.
    MVPVM 設計パターン • MVVMパターン – View:ユーザーインターフェースの外観や配 置や反応(インタラクション)を定義する – ViewModel:Viewの必要な情報をプロパティ で公開しユーザー入力やコマンドを処理する – Model:データの取得や管理を行いプログラム の処理の中核となる
  • 7.
    MVPVM 設計パターン • MVVMパターン View Model コマンド データバ インド ViewModel プロパ データ取得・更 ティ 新
  • 8.
    MVPVM 設計パターン • MVPパターン – View:ユーザーインターフェースの外観や配 置や反応(インタラクション)を定義する – Presenter:Viewのナビゲーションを管理し ユーザー入力をModelに伝える – Model:データの取得や管理を行いプログラム の処理の中核となる
  • 9.
    MVPVM 設計パターン • MVPパターン View Model 入力 Presenter ナビゲーショ データ取得・更 ン 新
  • 10.
    MVPVM 設計パターン • MVPVMパターン – View:ユーザーインターフェースの外観や配 置や反応(インタラクション)を定義する – ViewModel:Viewの必要な情報をプロパティ で公開しユーザー入力やコマンドをPresenter に渡す – Presenter:ViewやのViewModelのナビゲー ションを管理しユーザー入力をModelに伝える – Model:データの取得や管理を行いプログラム の処理の中核となる
  • 11.
    MVPVM 設計パターン • MVPVMパターン Presenter ナビゲーショ View ン データ取得・更 新 コマンド データバ データ更新依頼 インド ViewModel プロパ Model ティ
  • 12.
    ナビゲーション • ナビゲーション –MVVMパターンではどこがナビゲーションを 担当していたのでしょうか? – 答えの一つはメッセージ+ビヘイビアーです。 – ビヘイビアーはViewの分類になります。 – 「ViewModel から View を操作する」という こと葉を聞いたことがある人もいるでしょ う。 – 操作というのはメッセージを送ってメッセー ジボックスやダイアログを表示したりするこ とも多かったのです。
  • 13.
    ナビゲーション •メッセージボックス public class DialogMessageBehavior : Behavior<DependencyObject> { protected override void OnAttached() { base.OnAttached(); Messenger.Default.Register<DialogMessage>(AssociatedObject, p => Invoke(p)); } protected override void OnDetaching() { base.OnDetaching(); Messenger.Default.Unregister<DialogMessage>(AssociatedObject); } private void Invoke(object parameter) { DialogMessage message = parameter as DialogMessage; MessageBoxResult result = MessageBox.Show(message.Content, message.Caption, message.Button, message.Icon, m essage.DefaultResult, message.Options); message.ProcessCallback(result); } }
  • 14.
    ナビゲーション •ダイアログ public class DialogMessageBehavior : Behavior<Wndow> { protected override void OnAttached() { base.OnAttached(); Messenger.Default.Register<DialogMessage>(AssociatedObject, p => Invoke(p)); } protected override void OnDetaching() { base.OnDetaching(); Messenger.Default.Unregister<DialogMessage>(AssociatedObject); } private void Invoke(object parameter) { DialogMessage message = parameter as DialogMessage; AssociatedObject.DataContext = message.ViewModel; bool? result = AssociatedObject.ShowDialog(); message.ProcessCallback(result); } }
  • 15.
    ナビゲーション • ナビゲーション – MVVMパターンでは他にどこがナビゲーショ ンを担当していたのでしょうか? – 答えの一つはViewModel+DataTemplateです。 <DataTemplate DataType="{x:Type c:GreekGodViewModel}"> <TextBlock Text="{Binding Path=Name}" Foreground="Gold"/> </DataTemplate> – さらに DataTemplate をデータによって切り 替える DataTemplateSelector というのもあり ます。 – DataTemplate はViewの分類になります。
  • 16.
    ナビゲーション • DataTemplateSelector publicclass TaskListDataTemplateSelector : DataTemplateSelector { public override DataTemplate SelectTemplate(object item, DependencyObject container) { FrameworkElement element = container as FrameworkElement; if (element != null && item != null && item is TaskViewModel) { var taskitem = item as TaskViewModel; if (taskitem.Priority == 1) return element.FindResource("importantTaskTemplate") as DataTemplate; else return element.FindResource("myTaskTemplate") as DataTemplate; } return null; } }
  • 17.
    ナビゲーション • MVVMパターンは、View とViewModel は 疎結合でお互いに交換可能であるというこ とが利点の一つであるといわれていまし た。 • どうして今見てきたような密結合が生まれ てしまったのでしょうか? • ナビゲーションは View と ViewModel の両 方を知らないとできません、この場合 View に仕込んでますので ViewModel や 本 来ViewModel にあるべきデータが View に 出てきてしまいます。
  • 18.
    ナビゲーション • ナビゲーション –MVVMパターンではViewだけがナビゲーショ ンを担当していたのでしょうか? – 答えの一つはアプリケーションクラスです。 – アプリケーションクラスはMVVMパターンの 範囲外です。 – 範囲外であれば別に問題ないのでしょうか? – ナビゲーションを担当する Presenter があれ ばアプリケーションクラスはすっきりするは ずです。
  • 19.
    ナビゲーション • アプリケーションクラス protected overridevoid OnStartup(StartupEventArgs e) { var win = new Views.TwitterWindow(); this.MainWindow = win; var account = LoadAccount(); if (account == null) account = NewAccountWithDialog(); if (account != null) SaveAccount(account); else { MessageBox.Show("認証失敗"); return; } var vm = new ViewModel.TwitterViewModel( ConsumerKey, ConsumerSecret, account.Token); win.DataContext = vm; win.Show(); base.OnStartup(e); }
  • 20.
    プレゼンター • プレゼンターの役割 –View と ViewModel のインスタンス作成を行 います。 – View をパネルなどのコンテナに追加し、 DataContext に ViewModel をセットします。 – Model に表示すべきデータを要求し ViewModel にセットします。 – 上位の Presenter や ViewModel の依頼により 更新すべきデータを収集し Model を更新しま す。 – View と ViewModel のインスタンス解放を行 います。
  • 21.
    プレゼンター • プレゼンターの構成 –Presenter はパネルなどのコンテナで複数の Presenter を管理する Presenter と、ユーザー コントロールやダイアログなどの単一ビュー を管理するPresenter があります。 – View や ViewModel が階層構造になっている ように Presenter も階層構造になります。
  • 22.
    プレゼンター • プレゼンターの利点 –Application や ViewModel からプレゼンテー ションロジックを解放します。 – View と ViewModel は疎結合でお互いに交換 可能な状態に戻すことにより、再利用性を高 め View や ViewModel をライブラリ化しやす くします。 – View と ViewModel と Model 全てにアクセス 可能な存在なので、アンドゥ・リドゥの実装 場所に最適です。 – ViewModel から View をクローズするメッ セージは必要なくなります。
  • 23.
    プレゼンター • 親が子供を管理 –ダイアログ を表示させたいPresenterは ダイ アログを管理するPresenterを生成して、ダイ アログが閉じたら解放します。 – パネルなどのコンテナを管理するPresenterは、 パネルの中身を管理するPresenterをパネル内 に表示するときに生成してパネルから削除さ れるときに解放します。
  • 24.
  • 25.
    プレゼンター • WPFやSilverlightではこんな画面変化も可 能ですが、この場合はコンテナとなるパネ ルにストーリーボードを仕掛けて RenderTransform の TranslateTransform を変化させて表示を変えます。 • 最初にA画面とB画面の View と ViewModel を用意してA画面を表示範囲内 にB画面を表示範囲外に設定してストー リーボードを起動します。
  • 26.
    プレゼンター • MVVMパターンでは、 A画面とB画面の View と ViewModel を知っている何かの存 在が必要でコンテナの View で実行すると したら、かなりの密結合になってしまった と思います。
  • 27.
    プレゼンター • MVPVMパターンでは、 A画面のPresenter はA画面の View と ViewModel を知ってい て、 B画面のPresenterはB画面の View と ViewModel を知っています、コンテナの Presenterはコンテナの View と ViewModel の他に、 A画面とB画面の Presenterを知っています。 • 役割分担でき疎結合性も保たれます。
  • 28.
    まとめ • MVPVMパターンはMVVM の能力と機能を すべて利用でき、 MVPの拡張性からプレ ゼンテーションロジックの複雑さにも対応 できます。 • MVPVMパターンは View と ViewModel は 疎結合でお互いに交換可能な状態に戻すの に有効な手段です。 • 皆さんも検討してみたらどうでしょうか?