我正在处理开发我的应用程序的一个大问题。这是一个基于 C# 的 Winforms 基础应用程序,实现了 Model-View-Presenter 模式,但我不熟悉这种方法。我到处搜索,但没有找到我的问题的答案。
我需要知道如何使用这种模式来允许 winforms 之间的通信,以及演示者必须如何在不将演示者耦合到表单的情况下显示它们。我见过一种使用工厂模式的方法,但不明白如何实现它。
任何帮助或指向正确方向将不胜感激。
我正在处理开发我的应用程序的一个大问题。这是一个基于 C# 的 Winforms 基础应用程序,实现了 Model-View-Presenter 模式,但我不熟悉这种方法。我到处搜索,但没有找到我的问题的答案。
我需要知道如何使用这种模式来允许 winforms 之间的通信,以及演示者必须如何在不将演示者耦合到表单的情况下显示它们。我见过一种使用工厂模式的方法,但不明白如何实现它。
任何帮助或指向正确方向将不胜感激。
在 MVP 中,winforms 不应该相互通信。Form A 知道它的 Presenter A,Form B 知道它的 Presenter B
通常情况下,你会通过Presenter A修改带有Form A的model。Presenter B会监听model的变化,并相应地刷新Form B
如果您需要更多协调,您可以考虑使用应用程序控制器
请参阅http://dotnetslackers.com/articles/designpatterns/The-Presenter-in-MVP-Implementations.aspx
断言
Presenter 负责视图和模型之间的协调(如果遵循被动视图实现)。
这可能看起来像:
实例化 Presenter 并将自身注入 Presenter 的视图:
IPresenter presenter;
public View() { presenter = new Presenter(this) }
Presenter 实例化一个或多个视图并将自己注入到视图中:
IView1 view1;
public Presenter() { view1 = new View1(this) }
IView1 view1;
IView2 view2;
public Presenter() { view1 = new View1(this); view2 = new View2(this); }
例子
在您的情况下,协调多个视图的 Presenter 可能看起来像这样(伪):
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();
}
在本例中,由 Presenter 处理引发的事件View1
,数据设置在 中View2
,并View2
显示。
请记住,无论您的实现是什么,MVP 的目标是:
请记住,这只是演示者如何协调多个视图的基本示例。如果您想从演示者中抽象出您的视图创建,您可以将创建移动到演示者调用以创建视图并订阅其事件的另一个容器中。
我只是展示了一个虚拟代码,其中 2 个视图试图通过 Presenter 使用接口相互通信。这是一个简单的例子,让 mw 知道是否有问题。老实说,我还没有测试过这段代码。
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
界面或 2 个界面的第一个天气。如果您可以使用单个界面,则可能会有机会甚至容易。
我认为前面关于模型引发事件以使演示者了解更改的观点是正确的。我确实有一些评论,希望对您有用。
首先,View 实现可能不是一个单一的形式。有时,模型的一部分由一个单独的(可能是模态的)表单来维护是有意义的,该表单在视图中的作用就像一个复杂的控件。在这种情况下,表单之间的交互将是直接的。Presenter 不应该关心 View 的实现是如何完成的。
其次,当看起来需要交互的表单显然不是同一视图的一部分时(例如查找表单),我建议使用应用程序控制器模式。在这种情况下,当 Form A 需要执行某个功能(例如,“查找产品”或“编辑详细信息”)时,它将调用它自己的 Presenter 上的方法来执行此操作。然后,Presenter 在 Application Controller 上调用一个单独的方法(所有 Presenter 都引用它,它是一个单例),Application Controller 打开具有自己的 Presenter 的所需表单。在 WinForms 中,这一切都可以通过模态表单完成,在这种情况下,结果将通过调用链发回。或者,将需要应用程序控制器和演示者之间的一些事件引发 - 即
有关 MVP 中的应用程序控制器模式的更多信息,请参阅我的博客文章使用 MVP 模式