Communication between winforms in mvp pattern
我在开发应用程序时遇到了一个大问题。 这是一个基于C#的Winforms基础应用程序,实现了Model-View-Presenter模式,但是我对此方法并不陌生。 我到处搜索,但是找不到我的问题的答案。
我需要知道如何使用此模式在Winform之间进行通信,以及演示者如何在不将演示者耦合到表单的情况下显示它们。 我已经看到了使用Factory模式的方法,但不了解如何实现它。
任何帮助或指出正确方向的人,将不胜感激。
在MVP中,winforms不应相互通信。
表格A知道其演示者A,
表格B认识其主持人B
通常,您将通过Prensenter A使用表单A修改模型。演示者B将听取模型更改,并相应地刷新表单B。
如果需要更多协调,可以考虑使用应用程序控制器
参见http://dotnetslackers.com/articles/designpatterns/The-Presenter-in-MVP-Implementations.aspx
断言
演示者负责视图和模型之间的协调(如果遵循被动视图实现)。
可能看起来像:
实例化Presenter并将其注入Presenter的View:
1 2 | IPresenter presenter; public View() { presenter = new Presenter(this) } |
演示者实例化一个或多个视图并将其自身插入到视图中:
1 2 3 4 5 6 | IView1 view1; public Presenter() { view1 = new View1(this) } IView1 view1; IView2 view2; public Presenter() { view1 = new View1(this); view2 = new View2(this); } |
例
在您的情况下,协调多个视图的Presenter可能看起来像这样(伪):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | public class Presenter : IPresenter { IView1 view1; IView2 view2; public Presenter() { view1 = new View1(this); view2 = new View2(this); } private WireViewEvents() { view1.OnButtonClick += HandleButtonClickFromView1; } public void HandleButtonClickFromView1() { view2.SetSomeData(); view2.Show(); } |
在此示例中,演示者处理由
请记住,无论您采用哪种实施方式,MVP的目标都是:
- 关注点分离(UI与域逻辑分离)。
- 提高可测试性。
请注意,这只是演示者如何协调多个视图的基本示例。如果要从演示者中提取View创建内容,则可以将创建内容移到Presenter调用以创建视图并订阅其事件的另一个容器中。
我只是显示一个虚拟代码,其中2个视图试图通过Presenter使用接口相互通信。这是一个简单的示例,请让mw知道是否有故障。老实说,我没有测试过此代码。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 | namespace WindowsFormsApplication1 { internal class View1 : IView1 { public View1() { new Presenter(this); } public string Username { get; set; } public event EventHandler ShowDetails; } } namespace WindowsFormsApplication1 { internal class View2 : IView2 { public View2() { new Presenter(this); } public string Position { get; set; } } } namespace WindowsFormsApplication1 { public class Presenter { private readonly IView1 _view1; private readonly IView2 _view2; public Presenter(IView1 view1) { _view1 = view1; _view1.ShowDetails += ShowDetails; } private void ShowDetails(object sender, EventArgs e) { _view2.Position = _view1.Username =="My Name" ?"Arhchitect" :"Project Manager"; } public Presenter(IView2 view2) { _view2 = view2; } } } public interface IView1 { string Username { get; set; } event EventHandler ShowDetails; } public interface IView2 { string Position { get; set; } } |
但是在这个例子之后有一些注意事项。要开始使用您的应用程序,请尝试使用1
我认为前面提到的有关模型生成事件的要点是正确的,以使演示者知道更改是正确的。我确实有几点意见,希望对您有所帮助。
首先,View实现可能不是单一形式。有时,通过单独的(可能是模态的)形式维护模型的一部分是有意义的,该形式实际上就像是View中的复杂控件。在这种情况下,表单之间的交互将是直接的。演示者不应该关心View实现的完成方式。
其次,当看起来需要交互的表单显然不是同一视图的一部分时(例如,查找表单),我将使用"应用程序控制器"模式来重新命令。在这种情况下,当窗体A需要执行功能(例如"查找产品"或"编辑详细信息")时,它将在自己的Presenter上调用方法来执行此操作。然后,Presenter会在Application Controller上调用一个单独的方法(所有Presenters都引用该方法,这是一个单例),然后Application Controller打开具有自己的Presenter的所要求的表单。在WinForms中,所有这些都可以通过模式形式完成,在这种情况下,结果将通过调用链发送回去。或者,将需要在应用程序控制器和演示者之间进行一些事件引发,即,演示者在应用程序控制器上引发有关其已完成操作的事件,从而通知其他代表该事件的演示者。
有关MVP中的Application Controller模式的更多信息,请参见我的博客文章Using the MVP Pattern。