我没有看到问题 - 用户控件只不过是一个视图。演示者可以一次与多个视图进行交互。因此,在这种情况下,您的演示者可以参考 4 个视图(一个用于页面,两个用于用户控件,最后一个用于子用户控件)。
或者,您希望每个演示者有一个视图,在这种情况下,您可以将用户控件视为父视图(页面)的子视图,因此父视图需要为演示者上下冒泡视图交互。但是,我更喜欢演示者处理交互多个视图的早期方法。
请参阅有关如何完成布线的相关问题:https ://softwareengineering.stackexchange.com/questions/60774/model-view-presenter-implementation-thoughts
最后,您可能想看看 MVVM 模式,我认为它非常适合组合 UI。您将拥有控制视图和模型之间交互的视图模型,而不是演示者 - 但是,与演示者不同,视图模型不知道视图 - 而是视图观察(和更新)视图模型以呈现自身。在这里看到这篇文章(视图模型被称为演示模型): http: //www.codeproject.com/Articles/23340/Presentation-Model-in-Action
编辑:
老实说,我不喜欢你的任何方法。我喜欢 MVP 实现,其中演示者通过接口(无紧密耦合)持有对视图的引用,并且视图进行接线,即创建演示者实例并注入视图引用。演示者侦听视图事件并调用视图上的方法。View 从不直接调用演示者的方法。(MVP 的其他变体是可能的 - 请参阅我寻求的 SO 答案)。有了这个,我将解释我之前解释过的两种方法。
方法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。
方法二:
用户控件和页面交互。在这种情况下,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
...
}
}