mvp模式中winforms之间的通信

时间:2013-02-13 16:23:14

标签: winforms design-patterns communication mvp

我正在处理开发我的应用程序的一个大问题。它是C#上实现Model-View-Presenter模式的Winforms基础应用程序,但我是这个方法的新手。我到处搜索,但没有找到我的问题的答案。

我需要知道如何使用此模式来允许winforms之间的通信,以及演示者如何在不将演示者与表单耦合的情况下显示它们。我见过使用Factory模式的方法,但不明白如何实现它。

任何有关正确方向的帮助或观点都将受到赞赏。

4 个答案:

答案 0 :(得分:3)

<强>断言

Presenter负责视图和模型之间的协调(如果遵循Passive View实现)。

这可能如下所示:

实例化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();
}

在此示例中,View1引发的事件由Presenter处理,数据在View2中设置,并显示View2

请记住,无论您的实施是什么,MVP的目标都是:

  • 关注点分离(UI与域逻辑分开)。
  • 提高可测试性。

请注意,这只是Presenter如何协调多个视图的基本示例。如果要从演示者中抽象View创建,可以将创建移动到Presenter调用的另一个容器中以创建视图并订阅其事件。

答案 1 :(得分:3)

在MVP中,winforms不应该相互通信。 表格A知道其演示者A, 表格B知道其演示者B

通常,您将使用表格A到Prensenter A修改模型。演示者B将听取模型更改,并相应地刷新表格B

如果您需要更多协调,可以考虑使用应用程序控制器

请参阅http://dotnetslackers.com/articles/designpatterns/The-Presenter-in-MVP-Implementations.aspx

答案 2 :(得分:1)

我只是展示一个虚拟代码,其中2个视图试图通过Presenter使用接口相互通信。这是一个简单的例子,让我知道是否有什么东西在破碎。我没有测试过这段代码是诚实的。

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来决定您想要的第一个天气。如果您可以使用单个界面,可能会有机会甚至轻松。

答案 3 :(得分:0)

我认为之前提出的关于模型引发事件以使演示者了解变化的观点是正确的。我希望有一些评论希望有用。

首先,View实现可能不是单个表单。有时候,模型的一部分由一个单独的(可能是模态的)形式维护是有意义的,这个形式在View中真的像一个复杂的控件。在这种情况下,表格之间的互动将是直接的。 Presenter不应该关心View实现是如何完成的。

其次,当看起来需要交互的表单不是同一视图的明显部分(例如查找表单)时,我建议使用应用程序控制器模式。在这种情况下,当表单A需要执行一个函数(如“查找产品”或“编辑详细信息”)时,它将在它自己的Presenter上调用一个方法来执行该操作。然后,Presenter在应用程序控制器上调用一个单独的方法(所有Presenters都引用它,它是一个单例),应用程序控制器打开具有自己的Presenter的requried表单。在WinForms中,这可以用模态形式完成,在这种情况下,结果通过调用链发回。或者,需要在应用程序控制器和演示者之间引发一些事件 - 即,演示者在应用程序控制器上引发关于它已完成的事件的事件,并且因此通知归因于该事件的其他演示者。

有关MVP中应用程序控制器模式的更多信息,请参阅我的博文Using the MVP Pattern