問題はありません。ユーザーコントロールはビューに他なりません。また、プレゼンターは一度に複数のビューを操作できます。したがって、この場合、プレゼンターは、たとえば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
...
}
}