C#的WinForms模型 - 视图 - 演示(被动视图) [英] C# WinForms Model-View-Presenter (Passive View)

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

问题描述

我在开发C#中的WinForms应用程序。我已经在有限的GUI编程经验,我有学习上飞了很多。话虽这么说,这里就是我建立。

I'm developing a WinForms application in C#. I have limited experience in GUI programming, and I am having to learn a great deal on the fly. That being said, here's what I am building.

请参阅一般GUI看看下面的链接:

See the general GUI look at the following link:

现在,我已经做了很多的工作了,但在很糟糕的自主设计模式。我不知道该项目将以往任何时候都达到一定的规模,而且,正因为如此,现在是时候做一些大规模的重构。

Now, I have done a lot of the work already, but in the very bad Autonomous design pattern. I did not know the project would ever reach a certain size, and, as such, it is time to do some major refactoring.

我一直在研究大量关于GUI设计模式,而我希望实现该模式是被动视图(请参阅 http://martinfowler.com/ eaaDev / PassiveScreen.html )。我在寻找如何把这个一起一些帮助。

I have been studying a great deal about GUI design patterns, and the pattern I am wishing to implement is the Passive View (see http://martinfowler.com/eaaDev/PassiveScreen.html). I am looking for some help on how to bring this all together.

背景:

1)根据用户点击在树视图是什么,列表在底部左侧角落会显示可以填充编辑区域对象的列表。这些对象可能是一个文本框或一个DataGridView。用户可以切换列表中选择他/她想要在编辑器,看看有什么

1) Depending on what the user clicks in the "TreeView", the "List" in the bottom left-hand corner will display a list of objects that can populate the "Editor" area. These objects might be a TextBox or a DataGridView. The user toggles the List to choose what he/she wants to see in the "Editor"

2)模型本质上的数据和配置文件的文件夹。还有就是在给定的目录中运行外部程序,创建输出文件/文件夹等。这个节目我开发的目的是有效地管理/配置一个用户友好的方式这些对象

2) The model is essentially a folder with data and configuration files. There is an external program that runs on a given directory, creates output files/folders, etc. This program I am developing is designed to effectively manage/configure these objects in a user-friendly way

3)我一直在做事情的方式的问题是,它几乎是不可能的测试,因此移动到MVP式的被动视图设计模式

3) The problem with the way I have been doing things is that it is next to impossible to test, and hence the move to the MVP-esque Passive View design pattern

我试图让这个程序独立工作的视图。我一直没能寻找到一个更复杂的,交互式视图用于与被动视图模式的例子。

I am trying to make it so that the program works independently of the View. I have not been able to find any examples where a more complex, interactive view is used with the Passive View pattern.

问题:

1)我需要实现一个大接口/查看整个看该方案,然后实现子接口/子视图每个树视图,编辑器,记录仪等的?还是有更好的结构来这样做呢?

1) Do I need to implement one large interface/view for the entire "look" of the program, then implement sub-interfaces/sub-views for each of the TreeView, Editor, Logger, etc.? Or is there a better "structure" to doing this?

2)当谈到换手事件从视图中演示/控制器(不管术语你希望使用WRT被动视图设计模式),什么是我应该做这样的方式吗?有时候,我有需要更新简单的属性,有时候我需要一系列的步骤展开。

2) When it comes to "handing off" events from the View to the Presenter/Controller (whatever terminology you wish to use W.R.T. the Passive View design pattern), what is the way I should be doing this? Sometimes I have simple properties that need to be updated, and sometimes I need a whole series of steps to unfold.

我喜欢关于这个主题的建议和意见。我已经冲刷互联网,我还没有找到足够的例子来帮助我继续这个项目。

I would love suggestions and advice on this topic. I have scoured the Internet, and I haven't found adequate examples to help me continue with this project.

在此先感谢!

丹尼尔

推荐答案

下面是一个演示的使用MVP设计模式被动视图的概念一个简单的例子。因为我们使用被动视图的视图没有主持人的知识。主讲人只会订阅了查看发布的事件,并采取相应的行动。

Here is a simple example that demonstrates the concept of passive views using the MVP design pattern. Because we are using passive views the view has no knowledge of the presenter. The presenter will simply subscribe to events published by the view and act accordingly.

要开始了,我们需要定义我们的观点合同。这是使用的接口通常实现的,本质上来说,我们希望与我们的观点非常松耦合。我们想切换到不同的视图或事件创建单元测试的模拟意见的能力。

To start out we need to define a contract for our view. This is typically achieved using an interface, essentially, we want to have a very loose coupling with our view. We want the ability to switch to different views or event create mock views for unit testing.

下面是用来描述将用来显示客户信息的简单视图合同

Here is a contract that describes a simple view that will be used to display customer information

public interface ICustomerManagementView
{
    void InitializeCustomers(ICustomer[] customers);
    void DisplayCustomer(ICustomer customer);
    event EventHandler<EventArgs<ICustomer>> SelectedCustomerChanged;
}



它公开了一个单一的方法 InitializeCustomers ,这将是用于初始化我们从我们的模型对象视图。

It exposes a single method InitializeCustomers that will be used to initialize our view with objects from our model.

我们也有一个活动的 SelectedCustomerChanged 将由我们的主持人被用来接收通知发生在视图中的动作。

We also have an event SelectedCustomerChanged that will be used by our presenter to receive notification that an action has occurred in the view.

一旦我们有我们的合同,我们可以开始处理我们的主持人这些相互作​​用。

Once we have our contract we can start to handle these interactions in our presenter.

public class CustomerManagementPresenter
{
    private ICustomer _selectedCustomer;
    private readonly ICustomerManagementView _managementView;
    private readonly ICustomerRepository _customerRepository;

    public CustomerManagementPresenter(ICustomerManagementView managementView, ICustomerRepository customerRepository)
    {
        _managementView = managementView;
        _managementView.SelectedCustomerChanged += this.SelectedCustomerChanged;

        _customerRepository = customerRepository;

        _managementView.InitializeCustomers(_customerRepository.FetchCustomers());
    }

    private void SelectedCustomerChanged(object sender, EventArgs<ICustomer> args)
    {
        // Perform some logic here to update the view
        if(_selectedCustomer != args.Value)
        {
            _selectedCustomer = args.Value;
            _managementView.DisplayCustomer(_selectedCustomer);
        }
    }
}

在演示,我们可以使用所谓依赖注入另一种设计模式,提供访问我们的观点,我们可能会需要的任何模型类。在这个例子中,我有一个CustomerRepository是负责获取客户的详细信息。

In the presenter we can use another design pattern called dependency injection to provide access to our view and any model classes that we may need. In this example I have a CustomerRepository that is responsible for fetching customer details.

在构造函数中,我们有两个代码的重要线路,首先我们已经预订了SelectedCustomerChanged事件我们认为,正是在这里,我们可以进行相关的操作。其次,我们呼吁InitilaizeCustomers从库数据。

In the constructor we have two important lines of code, firstly we have subscribed to the SelectedCustomerChanged event in our view, it is here that we can perform associated actions. Secondly we have called InitilaizeCustomers with data from the repository.

在这一点上,我们还没有真正确定一个具体的实施我们的观点,我们需要做的就是创建一个对象器具的 ICustomerManagementView 的。例如,在Windows窗体应用程序,我们可以做以下

At this point we haven't actually defined a concrete implementation for our view, all we need to do is create an object that implements ICustomerManagementView. For example in a Windows Forms application we can do the following

public partial class CustomerManagementView : Form, ICustomerManagementView
{
    public CustomerManagementView()
    {
        this.InitializeComponents();
    }

    public void InitializeCustomers(ICustomer[] customers)
    {
        // Populate the tree view with customer details
    }

    public void DisplayCustomer(ICustomer customer)
    {
        // Display the customer...
    }

    // Event handler that responds to node selection
    private void CustomerTreeViewAfterSelect(object sender, TreeViewEventArgs e)
    {
        var customer = e.Node.Tag as ICustomer;
        if(customer != null)
        {
            this.OnSelectedCustomerChanged(new EventArgs<ICustomer>(customer));
        }
    }

    // Protected method so that we can raise our event
    protected virtual void OnSelectedCustomerChanged(EventArgs<ICustomer> args)
    {
        var eventHandler = this.SelectedCustomerChanged;
        if(eventHandler != null)
        {
            eventHandler.Invoke(this, args);
        }
    }

    // Our view will raise an event each time the selected customer changes
    public event EventHandler<EventArgs<ICustomer>> SelectedCustomerChanged;
}

如果我们想测试我们的表现逻辑,我们可以嘲笑我们的观点,并执行一些。断言

If we wanted to test our presentation logic we could mock our view and perform some assertions.

编辑:包括自定义事件参数

EDIT : Included custom event args

public class EventArgs<T> : EventArgs
{
    private readonly T _value;

    public EventArgs(T value)
    {
        _value = value;
    }

    public T Value
    {
        get { return _value; }
    }
}

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

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