【问题标题】:MVP in windows formsWindows窗体中的MVP
【发布时间】:2019-05-29 06:37:33
【问题描述】:

我想在我的 Windows 窗体应用程序中实现 MVPO 模式。如您所知,1:1 意味着一个演示者一个视图。

所以基本上我们可以:

public class MainPresenter
{
       IMainView _mainView;
       public MainPresenter(IMainView mainView)
       {
             _myView = myView;
       }
}

我的问题是一个演示者可以使用其他演示者吗,例如:

public class MainPresenter
{
       IMainView _mainView;
       ISomeOtherPresenter _otherPresenter;
       public MainPresenter(IMainView mainView, IOtherPresenter otherPresenter)
       {
             _mainView = myView;
             _otherPresenter = otherPresenter;
       }
}

作为参考,我浏览了 Robert Marquez 的视频教程。在他第 10 个视频系列的第 10 个视频系列中,他在另一个视频中使用了一个 rpesenter

Reference link

35:39 你会看到他的 MainPresenter 依赖于 IHelpAboutPresenter。

对我来说这是合乎逻辑的,因为如果HelpAboutView(表单)可以通过MainView 的按钮打开,那么MainPresenter 必须有权访问视频中显示的HelpAboutPresenter。如果不是那样怎么做,因为所有人都说1:1,而这里我们有1 presenter uses other presenter.

【问题讨论】:

  • 根据我的问题,这是关于一个演示者中的多个演示者(而不是多个视图)。

标签: c# winforms design-patterns mvp


【解决方案1】:

这样的交叉依赖有点小代码。如果您需要其他演示者的功能,则演示者可能有一些共同点。所以也许它们应该派生自同一个基类。然后他们可以轻松地共享逻辑,而不会使您的依赖关系图复杂化。

public class BasePresenter
{
    protected void SharedMethod()
    {
        //Code that you need to call from both presenters
    }
}

public class MainPresenter : BasePresenter
{
    IMyView _myView;

    public MainPresenter(IMyView myView)
    {
        _myView = myView;
    }

    private Foo()
    {
        SharedFunction();
    }
}

public class OtherPresenter : BasePresenter
{

    public OtherPresenter(IMyView myView) : base()
    {
        _myView = myView;
    }

    private Bar()
    {
        SharedMethod();
    }
}

【讨论】:

  • 是的,但是假设您在 MainView 上有一个按钮,当您单击它时会打开 OtherView。所以我们有 MainPresenter 和 OtherPresenter。如果 MainView 中的 byutton 可以访问 OtherView,您将如何处理?我所说的是将 OtherPresenter 注入 MainPresenter。您将如何以其他方式完成?
  • BasePresenter 将拥有显示OtherView 所需的所有代码。这样MainPresenterOtherPresenter 都可以呈现视图。当然,如果两个演示者都可以呈现该视图,您可能需要重命名它,因为如果 MainPresenter 也可以呈现它,它显然与 OtherPresenter 无关。
  • 你能根据情况添加代码来显示 MainView 有一个按钮来显示OtherView吗?那会很有帮助。或者使用我帖子中的链接,您能否查看 MainPresenter 上的真实代码并说出如何纠正注入的其他演示者?谢谢
【解决方案2】:

我会断言,这种方法本质上没有任何错误,尽管人们可能会采取另一种方式。

“主要”视图可能更像front controller。该模式通常与 Web 应用程序相关联,尽管它可能仍适用于桌面应用程序。例如,主 MDI 视图可能是 前端控制器

通常,前端控制器将具有某种调度机制,以使特定请求处理程序处理单个请求(例如桌面应用程序中的菜单单击,或基于 Web 的应用程序中基于 url 的资源)。因此,有一个轻微的间接性将前端控制器与具体实现分离。

在链接视频的情况下,这种关系更加耦合,因为About 框请求(如果我理解正确的话)不是由特定的请求处理程序而是由前端控制器处理的。

让这看起来很奇怪的是前端控制器是使用 MVP 模式实现的。

【讨论】:

  • 也许你可以帮助我理解。我是这样看的:我在 MainView 上有一个可以打开 SecondView 的按钮,而且我在 SecondView 上有一个可以打开 ThirdView 的按钮。所以对我来说,MainPresenter 应该在按钮单击时使用 SecondPresenter,因为 SecondView 由 SecondPresenter 维护。与由 ThirdPresenter 维护的 ThirdView 相同,由于它是从 SecondView 打开的,因此 SecondPresenter 应该使用它(ThirdPresenter)。
  • 通常,前端控制器和相关的演示者会注入请求调度程序。当您单击需要另一个视图才能打开相关演示者的按钮/菜单时,将通知_presenter.RequestSecondView(),并且演示者将通过调度程序调度所需的请求,例如_dispatcher.Send("SecondView")。现在,您可能不希望以这种方式在整个节目中弹出视图,因为导航有点不稳定,但为了您的示例,它很有用。
  • 只是为了补充我的最后一条评论:这完全是关于耦合。演示者的直接注入以及随后的方法调用以及对注入的IMessageDispatcher的调用,例如,在逻辑上执行相同的功能。唯一的区别是耦合,因为调度程序添加了一个间接层。
  • 嗯老实说我不明白。您能否根据我所写的内容为您的答案提供一些示例?表示我们是否有 AView 的 APresenter 和 BView 的 BPresenter 以及 CView 的 CPresenter。情况是在 AView 上有一个打开 BView 的按钮,在 BView 上有一个打开 CView 的按钮。很高兴看到如何做到这一点。在我看到它 APresenter 依赖于 AView 和 BPresenter 并且在 BPresenter 上依赖于 BView 和 CPresenter 并且最后在 CPresenter 上只有 CView
  • 添加一个例子会有些麻烦。您可以查看包含自定义复合 UI 的 this old commit。单击Clone or download 按钮获取压缩包。也许这可以揭示一些启示。如果您想给我发电子邮件,您可以在我的blog 上找到我的详细信息。
猜你喜欢
  • 1970-01-01
  • 2010-10-18
  • 1970-01-01
  • 1970-01-01
  • 2012-05-31
  • 1970-01-01
  • 2011-06-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多