我认为没有问题 - 用户控件只是一个视图。而且一个Presenter可以同时与多个视图进行交互。所以在这种情况下,您的Presenter可以引用4个视图(一个用于页面,两个用于用户控件和最后一个用于子用户控件)。
或者,您想要每个Presenter拥有单个视图,在这种情况下,您可以将用户控件视为父视图(页面)的子视图,因此父视图需要向上传递和向下传递为Presenter设计的视图交互。但是,我更喜欢前一种方法,即Presenter处理多个视图的交互。
请参见SO上有关如何进行连线的相关问题:
https://softwareengineering.stackexchange.com/questions/60774/model-view-presenter-implementation-thoughts 最后,您可能希望查看MVVM模式,我相信它非常适合组合UI。与Presenter不同,您将拥有View Model来控制视图和模型之间的交互-但是,View Model不知道视图-而是视图观察(并更新)View Model以呈现自身。请参见此处的文章(View Model被称为Presentation Model):
http://www.codeproject.com/Articles/23340/Presentation-Model-in-Action 编辑:
老实说,我不喜欢您的任何方法。我喜欢MVP实现,其中Presenter通过接口持有对View的引用(没有紧密耦合),而View进行连线,即创建Presenter实例并注入View引用。Presenter侦听View事件并调用View上的方法。View从不直接调用Presenter的方法。(MVP的其他变体是可能的-请参见我寻求的SO答案)。因此,我将解释我之前解释过的两种方法。
方法1:每个用户控件都是独立的视图。将有一个公共Presenter来处理多个视图。例如:
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();
...
}
public void OnSomeEvent()
{
_view2.DoOnSomeEvent();
}
...
}
public partial class MyPage : Page, IView1
{
public void Page_Load(...)
{
_presenter = new Presenter(this, usercontrol1);
}
...
}
基本思想是视图不会交叉通信。如果用户控件需要向页面传递信息,则会引发一个事件,由Presenter捕获并通知页面。视图被动地处理UI。
方法2:
用户控件和页面进行交互。在这种情况下,页面将充当最终的视图,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(...)
{
_presenter = new Presenter(this);
UserControl1.Foo += UserControl1_OnFoo();
UserControl1.XyzEvent += UserControl1_XyzEvent();
}
...
private void UserControl1_OnFoo(...)
{
OnFoo(..)
}
private void UserControl1_XyzEvent(...)
{
...
}
}