使用Windows表单实现MVC模式

104

我在哪里可以找到关于如何在Windows表单中完整实现MVC模式的好例子?

我在许多网站上找到了许多教程和代码示例(例如The Code Project和.NetHeaven),但其中许多更适用于观察者模式而非MVC。由于我要开发的应用程序是一个学校项目,所以我不愿使用像PureMVCMVC#这样的框架。


1
可能是重复的问题:如何在WindowsForms应用程序中实现MVC? - nawfal
6个回答

117
我认为应用程序彼此之间差异很大,我们对于应该如何编写应用程序的理解仍然非常有限。我曾经参与的Windows Forms应用程序各不相同。我见过的一些设计差异包括(包括大多数组合):
  • 直接访问数据库(2层)
  • 使用为特定应用程序编写的后端(3层)
  • 使用为许多应用程序编写的一组Web服务,无法更改以适应您的应用程序(面向服务的架构)
  • 通过CRUD操作进行更新
  • 使用命令模式进行更新(将命令发送到后端服务器)
  • 大量使用数据绑定/没有使用数据绑定
  • 大多数数据都类似于“表格”(例如发票),适用于标准网格控件/大部分UI数据需要自定义控件。
  • 一个开发人员/10或20个开发人员的团队(仅在UI上)
  • 大量使用模拟等单元测试/没有单元测试
因此,我认为不可能创建一个始终完全适合的MVC(或MVP)实现。

我看过的最好的关于MVC解释以及为什么要构建MVC系统的文章是Jeremy D Miller的"Build Your Own CAB"系列。通过这个系列,你应该能够更好地理解你的选项。

也应该考虑Microsoft的Smart Client Guidance(CAB/Microsoft Composite Application Block)。它有点复杂,但适用于需要良好适配性的应用程序。

选择一个Winforms项目中的MVC/MVP实现值得一读的概述。许多人喜欢PureMVC。我从未使用过它,但下次我需要一个MVC框架时会考虑它。

"Presenter First"是一种软件开发方法,将模型视图表示器(MVP)设计模式和测试驱动开发的思想结合起来。它允许你从客户语言编写测试用例。例如:

当我点击“保存”按钮时,文件应该被保存,未保存的文件警告应该消失。
我没有使用“Presenter First”的经验,但是当我有机会时,我会尝试一下,因为它看起来非常有前途。
您可能希望查看其他Stack Overflow问题,在这里在这里
如果您考虑在任何时候使用WPF,请查看Model-View ViewModel (MVVM)模式。这是一个非常好的视频,您应该看一下:Jason Dolinger on Model-View-ViewModelMVVM(Model View View Model)Design Pattern for Winforms提供了另一种选项,如果需要转换为WPF,则可能更容易。Magical.Trevor是Windows Forms的另一个MVVM示例,还包括基于属性名称的自动绑定。

同时,问问自己为什么要使用MVC。

  • 你希望能够对尽可能多的代码进行单元测试吗?
  • 你想让尽可能多的代码被重用吗?
  • 你想让你的代码库易于理解吗?
  • 对于特定项目而言,还有其他101个可以有效的原因。

一旦你明确了自己的目标,选择一种实现方式就变得更容易了。


@AgnelKurian,CAB是微软提供的一组构建应用程序的示例代码,现在它已经成为历史。 - Ian Ringrose
哈哈!是的,我现在记得那些“应用程序块”了。 - Agnel Kurian

45

更新:除了下面我之前的回答外,我建议阅读关于"Presenter First"方法的文章(特别是PDF文章)。

我建议使用MVP(实际上是PassiveView模式)而不是MVC。你不需要任何特殊的框架,这只是你组织代码的方式。

一个方法(通常我采用的方法)是将每个窗体分成三个实体:

  1. 一个presenter/controller类 - 这是你开发表单时实际上要开始的地方。这是大部分/全部的“业务”逻辑应该驻留的地方。
  2. 一个视图接口(IView),其中包含方法、属性和事件。这个接口是presenter所知道的你的表单的全部
  3. 最后,在你完成实现presenter和view(包括单元测试)后,你可以创建实际的表单类,并使其实现IView接口。然后就只需要向表单添加适当的控件并将它们连接到接口即可。

示例代码(简单的伪代码,仅供说明):

interface IView
{
    string Username { get; set; }
    string Password { get; set; }

    event EventHandler LogOnButtonClicked;

    void InformUserLogOnFailed();
    void MoveToMainScreen();
}

class Presenter
{
    public Presenter(IView view)
    {
        this.view = view;
        view.LogOnButtonClicked += new EventHandler(OnLogOnButton);
    }

    private void OnLogOnButton()
    {
        // we ask some service to verify the username/password
        bool isLogOnOk = logOnService.IsUserAndPasswordOk(view.Username, view.Password);
        if (isLogOnOk)
            view.MoveToMainScreen();
        else
        {
            view.Username = "";
            view.Password = "";
            view.InformUserLogOnFailed();
        }
    }

    private IView view;
}

class Form : IView
{
    public Form()
    {
        presenter = new Presenter(this);
    }

    public string Username
    {
        get { return TextBoxUsername.Text; }
        set { TextBoxUsername.Text = value; }
    }

    public string Password
    {
        get { return TextBoxPassword.Text; }
        set { TextBoxPassword.Text = value; }
    }

    public void InformUserLogOnFailed()
    {
        MessageBox.Show("Invalid username or password.");
    }

    public void MoveToMainScreen()
    {
        // code for opening another form...
    }

    private Presenter presenter;
}

7
这是一种名为PassiveView的MVP变体实现。在被动视图中,视图不应选择它的Presenter。 有一个类似的例子(但视图真正被动)可以参考这个样例http://www.danieleteti.it/?p=221(Delphi语言示例)。 - Daniele Teti

6
你看过PureMVC吗?我发现一旦开始构建特定的实现,没有人能够达成对MVC的真正理解。更新:你可以从一些更简单的东西开始构建你自己的项目,例如MobileMVC。紧凑框架代码应该可以在Windows上编译/运行。由于这是一个学校作业,我建议你花些时间了解MVC的工作原理。

我有一个学校作业,需要编写一个非常简单的书店管理应用程序,但我不太想使用像PureMVC这样的框架。我正在寻找更简单的东西。 - kjv

3

您可能想了解一下差分执行

这是在SourceForge上的实现。

在我看来,它比MVC有了很大的改进,虽然它仍然相当不寻常。


2
这是一个使用Windows Forms自己实现MVC的好例子,可以在这里找到。源代码也包含在内。
当您阅读、学习和编写此任务的代码时,您会发现有很多关于如何实现MVC的争议。这个例子是一个简单的案例,反映了关注点的分离以及连接所需的良好示例。
当你离开学校后,你可能想退而求其次,使用像其他帖子推荐的框架一样。

2

微软复合接口应用程序块最初作为MVC实现(它实现了其他模式)而开始。然而,发布版本演变成MVP实现,可以说是对MVC概念的一种不同解释。

如果您愿意检查非常完整(并且有些复杂)的MVP实现代码,您可以在Microsoft Smart Client软件工厂的组件之一中找到MS-CAB。它附带源代码。您可以在此处找到它。祝好运!


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接