关于如何为数据绑定 windows 表单应用程序实施 MVP 模式的一些指南

Some guidelines on how to implement MVP pattern for a data binding windows forms app

我想构建一个使用数据绑定的 windows 表单应用程序,我假设它是使用绑定源。我将把大型数据表的不同部分加载到 3 个单独的数据网格视图,并且我将适应如下操作:

1) 将整列数据从一个数据网格视图移动到另一个数据网格视图

2) 编辑单元格内的值

3) 过滤数据

4) 将来,还包括获取实时数据,并显示任何新数据。

我的第一种方法(对我来说似乎合乎逻辑)是入口点可能是演示者,然后演示者将创建视图。然而,我正在认真考虑另一种方法,即使用单独的 class 创建演示者、视图和模型。

第一个问题是:在这种特定情况下,这两种方法中的一种可能更好吗?

第二个问题:现在我的过滤是即时的。但是,如果我实现 MVP,那么这意味着过滤操作必须通过 Presenter class,它会更新模型,然后返回到 Presenter,它会更新视图。也许这对用户来说不是一种视觉上吸引人的体验。如果视图直接连接到模型以进行此类操作(受监督的 MVP),会不会更好?

第三:为将弹出的其他用户控件创建演示者是否是正确的方法,但他们将无法直接访问模型,而是必须先通过应用程序的主要演示者?

这就是我用 Winforms 完成 MVP 的方式,并且效果很好,

1) Model - View绑定的数据结构

2)View——所有可视化逻辑的封装

3) Controller - 对View/Model

执行的所有操作的封装

下面是一个例子,

//Model
class Person : INotifyPropertyChanged
{
    //Properties with notification
}

//Views
abstract class View
{
    //Base class for all views
    public abstract void SetDataSource(object source);
    protected virtual void Refresh();
    public abstract void Show();
}

//Data grid view
class DataGridView : View
{
    private Controller _controller = null;
    private System.Windows.Forms.DataGrid _grid = new System.Windows.Forms.DataGrid();

    public DataGridView(Controller controller)
    {
        _controller = controller;
    }

    public override void SetDataSource(object dataSource)
    {
        _grid.DataSource = dataSource;
    }

    public override void Show()
    {
    }

    protected override void Refresh
    {
        _grid.Refresh();
    }
}

//Controllers
abstract class Controller
{
    //Base controller
    public abstract void Init();
    public abstract void Show();
    public abstract void ViewChanged(object args);//To receive view changes
}

//Person presenter
class PersonGridController : Controller
{
    private DataGridView _view = new DataGridView(this);
    private BindingList<Person> _persons = new BindingList<Person>();

    public override void Init()
    {
        //Initialize persons
        //Optional, start thread/timer to update persons in background
    }

    public override void Show()
    {
        _view.SetDataSource(_persons);
        _view.Show();
    }

    public override void ViewChanged(object args)
    {
        //Based on arguments, perform filter, edit, save, etc.
    }
}

这是我过去使用的基本结构。 Controller 和 View 之间存在耦合,我们可以使用依赖注入(使用 Unity 等框架)将其解耦,并将创建 View 的逻辑移到 Controller 之外。我还有一个工作区管理器 class,它在 Window 中托管视图。如果想简单点,View可以继承自Window class.

关于您的问题,

1) 应通过数据源将列从一个网格移动到另一个网格

2 & 3) 可以使用 Controller.ViewChanged() 事件

完成过滤和编辑

4) 可以使用 Controller.Init() 函数进行实时更新,可以生成一个线程以便在后台更新数据源。