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, message.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 は疎
  結合でお互いに交換可能な状態に戻すのに
  有効な手段です。
• 皆さんも検討してみたらどうでしょうか?

RIAアーキテクチャー研究会 第3回 セッション4 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, message.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 は疎 結合でお互いに交換可能な状態に戻すのに 有効な手段です。 • 皆さんも検討してみたらどうでしょうか?