WinForms 中的模型-视图-展示器 [英] Model-View-Presenter in WinForms

查看:20
本文介绍了WinForms 中的模型-视图-展示器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我第一次尝试使用 WinForms 实现 MVP 方法.

I am trying to implement the MVP method for the first time, using WinForms.

我正在尝试了解每一层的功能.

I am trying to understand the function of each layer.

在我的程序中,我有一个 GUI 按钮,单击该按钮会打开一个 openfiledialog 窗口.

In my program I have a GUI button that when clicked upon opens a openfiledialog window.

所以使用MVP,GUI处理按钮点击事件,然后调用presenter.openfile();

So using MVP, the GUI handles the button click event and then calls presenter.openfile();

在presenter.openfile()中,是否应该将该文件的打开委托给模型层,或者因为没有数据或逻辑要处理,它是否应该简单地根据请求采取行动并打开openfiledialog窗口?

Within presenter.openfile(), should that then delegate the opening of that file to the model layer, or as there is no data or logic to process, should it simply act on the request and open the openfiledialog window?

更新:我决定提供赏金,因为我觉得我需要进一步的帮助,最好根据我下面的具体观点量身定制,以便我了解上下文.

Update: I have decided to offer a bounty as I feel I need further assistance on this, and preferably tailored to my specific points below, so that I have context.

好的,在阅读了 MVP 之后,我决定实施被动视图.实际上,我将在 Winform 上拥有一堆控件,这些控件将由 Presenter 处理,然后将任务委派给模型.我的具体观点如下:

Okay, after reading up on MVP, I have decided to implement the Passive View. Effectively I will have a bunch of controls on a Winform that will be handled by a Presenter and then the tasks delegated to the Model(s). My specific points are below:

  1. 当winform加载时,它必须获得一个树状视图.我认为视图应该因此调用一个方法是否正确,例如:presenter.gettree(),这反过来将委托给模型,该模型将获取树视图的数据,创建并配置它,将其返回给演示者,然后将传递给视图,然后将其简单地分配给面板?

  1. When the winform loads, it has to obtain a treeview. Am I correct in thinking that the view should therefore call a method such as: presenter.gettree(), this in turn will delegate to the model, which will obtain the data for the treeview, create it and configure it, return it to the presenter, which in turn will pass to the view which will then simply assign it to, say, a panel?

这对 Winform 上的任何数据控件都一样吗,因为我也有一个 datagridview?

Would this be the same for any data control on the Winform, as I also have a datagridview?

我的应用程序,有许多具有相同程序集的模型类.它还支持带有需要在启动时加载的插件的插件架构.视图是否会简单地调用一个 Presenter 方法,该方法又会调用一个加载插件并在视图中显示信息的方法?哪个层将控制插件引用.视图会包含对他们或演示者的引用吗?

My App, has a number of model classes with the same assembly. It also supports a plugin architecture with plugins that need to be loaded at startup. Would the view simply call a presenter method, which in turn would call a method that loads the plugins and display the information in the view? Which tier would then control the plugin references. Would the view hold references to them or the presenter?

我认为视图应该处理关于呈现的每一件事,从树视图节点颜色到数据网格大小等,我是否正确?

Am I correct in thinking that the view should handle every single thing about presentation, from treeview node colour, to datagrid size, etc?

我认为它们是我的主要关注点,如果我了解这些流程应该如何,我想我会没事的.

I think that they are my main concerns and if I understand how the flow should be for these I think I will be okay.

推荐答案

这是我对 MVP 和您的具体问题的谦虚看法.

This is my humble take on MVP and your specific issues.

首先,用户可以与之交互或仅显示的任何内容都是视图.这种视图的规律、行为和特征由接口描述.该界面可以使用 WinForms UI、控制台 UI、Web UI 甚至根本没有 UI 来实现(通常在测试演示者时)——具体的实现并不重要,只要它遵守其视图界面的规则.

First, anything that a user can interact with, or just be shown, is a view. The laws, behavior and characteristics of such a view is described by an interface. That interface can be implemented using a WinForms UI, a console UI, a web UI or even no UI at all (usually when testing a presenter) - the concrete implementation just doesn't matter as long as it obeys the laws of its view interface.

第二,视图始终由演示者控制.界面也描述了这种演示者的规律、行为和特征.该接口对具体的视图实现没有兴趣,只要它遵守其视图接口的规律即可.

Second, a view is always controlled by a presenter. The laws, behavior and characteristics of such a presenter is also described by an interface. That interface has no interest in the concrete view implementation as long as it obeys the laws of its view interface.

第三,由于演示者控制着它的视图,为了最小化依赖性,让视图完全了解它的演示者实际上没有任何好处.演示者和视图之间有一个约定的合同,并由视图接口声明.

Third, since a presenter controls its view, to minimize dependencies there's really no gain in having the view knowing anything at all about its presenter. There's an agreed contract between the presenter and the view and that's stated by the view interface.

第三的含义是:

  • 演示者没有视图可以调用的任何方法,但视图具有演示者可以订阅的事件.
  • 演示者知道它的观点.我更喜欢通过对具体演示者的构造函数注入来实现这一点.
  • 视图不知道是什么演示者在控制它;永远不会提供任何演示者.

对于您的问题,上面的代码可能看起来像这样:

For your issue, the above could look like this in somewhat simplified code:

interface IConfigurationView
{
    event EventHandler SelectConfigurationFile;

    void SetConfigurationFile(string fullPath);
    void Show();
}

class ConfigurationView : IConfigurationView
{
    Form form;
    Button selectConfigurationFileButton;
    Label fullPathLabel;

    public event EventHandler SelectConfigurationFile;

    public ConfigurationView()
    {
        // UI initialization.

        this.selectConfigurationFileButton.Click += delegate
        {
            var Handler = this.SelectConfigurationFile;

            if (Handler != null)
            {
                Handler(this, EventArgs.Empty);
            }
        };
    }

    public void SetConfigurationFile(string fullPath)
    {
        this.fullPathLabel.Text = fullPath;
    }

    public void Show()
    {
        this.form.ShowDialog();        
    }
}

interface IConfigurationPresenter
{
    void ShowView();
}

class ConfigurationPresenter : IConfigurationPresenter
{
    Configuration configuration = new Configuration();
    IConfigurationView view;

    public ConfigurationPresenter(IConfigurationView view)
    {
        this.view = view;            
        this.view.SelectConfigurationFile += delegate
        {
            // The ISelectFilePresenter and ISelectFileView behaviors
            // are implicit here, but in a WinForms case, a call to
            // OpenFileDialog wouldn't be too far fetched...
            var selectFilePresenter = Gimme.The<ISelectFilePresenter>();
            selectFilePresenter.ShowView();
            this.configuration.FullPath = selectFilePresenter.FullPath;
            this.view.SetConfigurationFile(this.configuration.FullPath);
        };
    }

    public void ShowView()
    {
        this.view.SetConfigurationFile(this.configuration.FullPath);
        this.view.Show();
    }
}

除上述之外,我通常有一个基本的 IView 接口,我在其中存储 Show() 和我的视图通常受益的任何所有者视图或视图标题.

In addition to the above, I usually have a base IView interface where I stash the Show() and any owner view or view title that my views usually benefit from.

回答您的问题:

1. 当winform 加载时,它必须获得一个树视图.我认为视图应该因此调用一个方法是否正确,例如:presenter.gettree(),这反过来将委托给模型,该模型将获取树视图的数据,创建并配置它,将其返回给演示者,它又将传递给视图,然后视图将其简单地分配给,比如说,一个面板?

我会在调用 IConfigurationView.Show() 之前从 IConfigurationPresenter.ShowView() 调用 IConfigurationView.SetTreeData(...)代码>

I would call IConfigurationView.SetTreeData(...) from IConfigurationPresenter.ShowView(), right before the call to IConfigurationView.Show()

2. 这对 Winform 上的任何数据控件都一样吗,因为我也有一个 datagridview?

是的,我会为此调用 IConfigurationView.SetTableData(...).由视图来格式化提供给它的数据.演示者只是遵守视图的约定,它需要表格数据.

Yes, I would call IConfigurationView.SetTableData(...) for that. It's up to the view to format the data given to it. The presenter simply obeys the view's contract that it wants tabular data.

3. 我的应用程序,有许多具有相同程序集的模型类.它还支持带有需要在启动时加载的插件的插件架构.视图是否会简单地调用一个 Presenter 方法,该方法又会调用一个加载插件并在视图中显示信息的方法?哪个层将控制插件引用.视图会包含对他们或演示者的引用吗?

如果插件是视图相关的,那么视图应该知道它们,而不是演示者.如果它们都是关于数据和模型的,那么视图不应该与它们有任何关系.

If the plugins are view-related, then the views should know about them, but not the presenter. If they are all about data and model, then the view shouldn't have anything to do with them.

4. 我认为视图应该处理关于呈现的每一件事,从树视图节点颜色到数据网格大小等,我是否正确?

是的.将其视为提供描述数据的 XML 的演示者和获取数据并将 CSS 样式表应用于数据的视图.具体而言,演示者可能会调用 IRoadMapView.SetRoadCondition(RoadCondition.Slippery),然后视图将道路渲染为红色.

Yes. Think about it as the presenter providing XML that describes data and the view that takes the data and applies a CSS stylesheet to it. In concrete terms, the presenter might call IRoadMapView.SetRoadCondition(RoadCondition.Slippery) and the view then renders the road in red color.

点击节点的数据怎么样?

5. 如果当我点击树节点时,我是否应该将特定节点传递给演示者,然后演示者会从中计算出它需要什么数据,然后询问在将数据呈现回视图之前为该数据建模?

如果可能,我会一次性传递在视图中呈现树所需的所有数据.但是,如果某些数据太大而无法从一开始就传递,或者如果它本质上是动态的并且需要来自模型的最新快照"(通过演示者),那么我会添加类似 event LoadNodeDetailsEventHandler LoadNodeDetails 到视图接口,以便演示者可以订阅它,从模型中获取 LoadNodeDetailsEventArgs.Node 中节点的详细信息(可能通过其某种 ID),以便视图可以在事件处理程序委托返回时更新其显示的节点详细信息.请注意,如果获取数据可能太慢而无法提供良好的用户体验,则可能需要这种异步模式.

If possible, I would pass all data needed to present the tree in a view in one shot. But if some data is too large to be passed from the beginning or if it's dynamic in its nature and needs the "latest snapshot" from the model (via the presenter), then I would add something like event LoadNodeDetailsEventHandler LoadNodeDetails to the view interface, so that the presenter can subscribe to it, fetch the details of the node in LoadNodeDetailsEventArgs.Node (possibly via its ID of some kind) from the model, so that the view can update its shown node details when the event handler delegate returns. Note that async patterns of this might be needed if fetching the data might be too slow for a good user experience.

这篇关于WinForms 中的模型-视图-展示器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆