3

アプリケーションに Model-View-Presenter デザイン パターンを実装しようとしています。MVP パターンの一般的な概念はわかっていますが、ネストされたユーザー コントロールを使用してそれを実現するのに苦労しています。

実装できる可能性のあるシナリオがいくつかありますが、実装する前にあなたの意見を聞きたいです。

私が理解しようとしているのは「概念」であるため、コードを投稿しても問題ないと思います。

したがって、シナリオは次のとおりです。

2 つのユーザー コントロールを接続するために使用される 1 ページ。これらのユーザー コントロールの 1 つに、子ユーザー コントロールが含まれています。この場合、MVP パターンを回避するにはどうすればよいですか?

1 Page
  1 UC
  1 UC
     1 SubUC

編集:

基本的に私が知りたいのは、両方のユーザー コントロールで MVP を使用して 2 つのビュー (親と子) 間で対話する方法です。

ASP.net で MVP なしの例を示します: http://pastie.org/5452134

MVP では、CodeBehind を使用してこの種のイベントに登録しますか? この親と子のユーザーコントロールが両方とも MVP パターンを使用することを知っています。それとも、プレゼンターはこのやり取りに含まれますか?

最終的に、コードを次のように変更できます: http://pastie.org/5452180

でもMVPのパターンを考えるとこれでいいのかなぁ…。

それとも、次のようなアプローチが必要ですか: http://pastie.org/5452174

上記の例はすべて、親ビューの CodeBehind に記述されています。この中のどれかは正しいですか?そうでない場合、より良いアプローチを使用してこれを達成するにはどうすればよいですか

編集 2: https://github.com/frederikprijck/ASP.NET-MVPで、サンプル アプローチを使用してソリューションを追加しました 。

4

1 に答える 1

5

問題はありません。ユーザーコントロールはビューに他なりません。また、プレゼンターは一度に複数のビューを操作できます。したがって、この場合、プレゼンターは、たとえば4つのビュー(1つはページ用、2つはユーザーコントロール用、最後の1つはサブユーザーコントロール用)の参照を持つことができます。

または、プレゼンターごとに単一のビューを設定する必要があります。そのような場合、ユーザーコントロールを親ビュー(ページ)の子ビューとして表示できるため、親ビューはプレゼンター向けのビューの相互作用を上下にバブルする必要があります。ただし、インタラクションを処理するプレゼンターが複数のビューを処理する以前のアプローチをお勧めします。

配線がどのように行われるかについては、SOに関するこの関連質問を参照してください:https ://softwareengineering.stackexchange.com/questions/60774/model-view-presenter-implementation-thoughts

最後に、コンポジションUIに最適であると私が信じているMVVMパターンを確認することをお勧めします。プレゼンターの代わりに、ビューとモデル間の相互作用を制御するビューモデルがありますが、プレゼンターとは異なり、ビューモデルはビューを認識しません。ビューはビューモデルを監視(および更新)してレンダリングします。こちらの記事を参照してください(ビューモデルはプレゼンテーションモデルと呼ばれます): http: //www.codeproject.com/Articles/23340/Presentation-Model-in-Action

編集

正直なところ、私はあなたのアプローチのどれも好みません。私は、プレゼンターがインターフェイスを介してビューへの参照を保持し(密結合なし)、ビューが配線を行う、つまりプレゼンターインスタンスを作成し、ビュー参照を挿入するMVP実装が好きです。プレゼンターは、ビューイベントをリッスンし、ビューのメソッドを呼び出します。Viewがプレゼンターのメソッドを直接呼び出すことはありません。(MVPの他のバリエーションも可能です-私が探していたSOの答えを参照してください)。これで、先ほど説明した2つのアプローチについて説明します。

アプローチ1

各ユーザーコントロールは独立したビューです。複数のビューを処理する共通のプレゼンターがあります。例えば、

public class Presenter1
{
    IView1 _view1;
    IView2 _view2;

    public Presenter1(IView1 view1, IView2 view2)
    {
        _view1 = view1;
        _view2 = view2;

        _view1.OnSave += OnSave;
        _view1.OnSomeEvent += OnSomeEvent;
        _view2.OnFoo += OnFoo;
    }

    public void OnSave()
    {
        var data1 = _view1.GetData();
        var data2 = _view2.GetData();
        // update model
        ...
    }

    public void OnSomeEvent()
    {
       // inform view2 about it
       _view2.DoOnSomeEvent();
    }

    ...
}

public partial class MyPage : Page, IView1
{
   public void Page_Load(...)
   {
     //do wire up
     _presenter = new Presenter(this, usercontrol1);
   }
   ...
}

基本的な考え方は、ビューはクロストークを行わないということです。ユーザーコントロールがページに何かを通知する必要がある場合、プレゼンターによってキャッチされたイベントが発生し、それについてページに通知します。ビューはパッシブであり、UIを処理します。

アプローチ2:

ユーザーコントロールとページは相互作用します。このような場合、Pageは最終的なビューとして機能し、Presenterはそれを参照します。コントロールのイベントはページごとに処理され、必要に応じてページがイベントをバブルアップします。例えば、

IView1 : IView2 { }

public class Presenter1
{
   IView1 _view1;

   public Presenter1(IView1 view1)
   {
       _view1 = view1;

       _view1.OnSave += OnSave;
       _view1.OnSomeEvent += OnSomeEvent;
       _view1.OnFoo += OnFoo;
   }
   ...
}

public partial class MyPage : Page, IView1
{
       public void Page_Load(...)
       {
         //do wire up
         _presenter = new Presenter(this);

         // handle user control events
         UserControl1.Foo += UserControl1_OnFoo();
         UserControl1.XyzEvent += UserControl1_XyzEvent();

       }
       ...

       private void UserControl1_OnFoo(...)
       {
          // bubble up to presenter
          OnFoo(..)
       }

       private void UserControl1_XyzEvent(...)
       {
          // private interaction (purely about some UI manipulation), 
          // will not be bubble up to presenter
          ...
       }
}
于 2012-11-29T09:13:47.103 に答える