8

编辑:接受 Chris Holmes 的回复,但如果有人想出更好的方法,随时准备重构!谢谢!

用 MVP 做一些 winforms 什么是将实体传递到另一个视图的最佳方式。

假设我有一个CustomerSearchView/Presenter,在 doubleClick 上我想显示CustomerEditView/Presenter. 我不想让我的视图知道模型,所以我不能创建一个带有ICustomerin 参数的 ctor。

我的反应是,

CustomerSearchView创建一个新的CustomerEditView,它创建它自己的演示者。然后我CustomerSearchView会做类似的事情:

var customerEditView = new CustomerEditView();
customerEditView.Presenter.Customer = this.Presenter.SelectedCustomer;

其他可能的方法是一个CustomerDTO类,并让一个CustomerEditView接受其中的一个CustomerDTO,但我认为这是很多简单的工作。

对不起,基本问题,但我能找到的所有例子都没有达到这一点,这是一个棕地项目,到目前为止使用的方法让我头疼......

4

5 回答 5

4

我不知道你是如何表达你的观点的,所以在这里给你具体的建议有点困难。这就是我以前做过这种事情的方式:

我们所做的是让 CustomerSearchViewPresenter 触发类似 OpenCustomer(customerId) 的事件。(假设您的搜索视图只有几条客户数据,而 customerId 就是其中之一。如果您的搜索视图列出了整个客户对象,那么您可以调用 OpenCustomer(customer)。但我不会构建搜索视图并允许它填充整个对象......我们在数据方面保持我们的搜索视图轻量级。)

应用程序中的其他地方是一个事件处理程序,它侦听 OpenCustomer() 事件并执行创建带有 Presenter 的新 CustomerEditView 的任务(我将推迟到我的 IoC 容器为我做这些事情,所以我不不必在任何地方使用“new”关键字)。创建视图后,我们可以将 id(或客户对象)传递给新的 CustomerEditView,然后显示它。

负责列出 OpenCustomer() 事件并执行 CustomerEditView 创建的此类通常是我们应用程序中的某种控制器类。

为了进一步简化这种情况,我采用了另一种方法:在应用程序或模块启动时创建 CustomerSearchView (&presenter) 和 CustomerEditView (&presenter)。当 CustomerSearchView 需要打开一个 Customer 进行编辑时,CustomerEditView 成为 OpenCustomer 事件的响应者并将数据加载到它自己中,并且知道如何在它应该做的任何容器中显示它自己。

所以有多种方法可以做到这一点。

于 2009-02-10T23:04:56.687 回答
1

怎么样:

//In CustomerSearchPresenter
var presenter = new CustomerEditPresenter();
var customerEditView = new CustomerEditView(presenter);
presenter.SetCustomer(customer);

//In CustomerEditPresenter
public void SetCustomer(customer)
{
    View.Name = customer.Name;
    View.Id = customer.Id;
    ...
}

认为您的客户搜索视图应该只委托给它的演示者,您需要执行一个操作。

于 2009-02-10T20:39:43.760 回答
0

在任何 MVP 代码中获得自然流程有几个关键的见解:

  1. 驱动视图的是演示者,而不是相反。
  2. 因为1.视图不需要知道presenter的存在。更少的依赖通常意味着更容易维护。

在 C# 中,我发现在将演示者与视图分离时,事件是一项重要资产。上一个答案中的更多详细信息:WinForms 中的 Model-View-Presenter

于 2011-08-16T23:02:35.753 回答
0
  1. 我会看看 MS Prism 4,以及它们漂亮的导航界面。另请查看 Silverlight 和 WCF 导航。他们做得很好,可以处理一些事情,比如提示用户从“脏”表单中确认,并取消。

  2. 我也会查看 WCF 中的 PageFunction() 文档,了解如何从另一个页面“调用”页面并获取信息。

这是它的工作原理(javascript,抱歉):

用户双击客户列表中的客户:

CustomerList.onDblClick(customerId){

  app.fireEvent('customerEditRequest', id)

}

...

app.onCustomerEditRequest(id){
  this.mainRegion.requestNavigate('customers/edit', id);
}

如果导航到编辑视图成功...

CustomerEditView.onNavigatedTo(context){
  this.model.load(context.parameters.id));
}

CustomerEditView.onSaveButtonClick(){
  this.model.save();
  app.fireEvent('customerEdited', id);
}

...

app.onCustomerEdited(id){
  app.mainRegion.requestNavigate('customerlist', id);
}

有几种不同的方法可以做到:

  1. 从客户列表向编辑表单发送回调函数。编辑表单会调用它,当它被调用时你可以做你想做的事。

  2. 在您收听并做出反应的“customerEdited”事件上引发编辑表单(没有应用程序范围的总线)

  3. 使用应用程序范围的事件总线集中管理事件,如图所示。

于 2012-05-20T20:50:42.883 回答
0

我曾经让我的观点与他们的演讲者交流,但已经远离了。它不符合模式的原始定义(这本身并不是偏离只是实现这些好处的一个促成因素的原因)。理想情况下,视图应该保持尽可能低的依赖关系和尽可能少的依赖关系。View 应该通过委托/事件/一些“即发即弃”机制与 Presenter(任何“观察者”)进行通信。事实上,我已经在 MVP 中引入了一个控制器,专门用于拦截 View 事件并重新触发 Presenter(很少)与 Presenter 进行通信,或者与系统或特定于 Presenter 的事件总线进行通信 - 使我能够在不接触视图的情况下更改用户操作警报机制。但是必须小心使用事件总线;很快你就开始在那里抛出所有事件,应用程序在处理事件时变得健谈/陷入困境,并且事件不是 .Net 中最快的事情。同步是一个额外的问题,特别是如果您的应用程序需要与您的用户进行更“对话”的交互。

应该记住,尽管 Presenter 是特定于视图/流程的,但视图(和视图模型)可以被重用;让 View 与 Presenter 处于包含/委托关系中会强烈地耦合 View/限制其重用。这可以通过一些 DI 来减少,但我发现 DI 容器在大多数情况下是不必要的复杂性(因为我必须知道如何创建对象以及在创建/测试后多久将一个对象更改为另一个语义相似的对象?)。除了另一层/增加了更多的模糊性/使事情更难以调试/跟踪之外,具体的依赖性无处可去。不过最近一直处于“简单”状态,并且大多数情况下更喜欢为大多数应用程序进行工厂/对象创建/ORM 映射,因为有一个“一对一”

此外,View 观察 MVP 中的 Model 还是很可行的(就像在 MVC 中一样),所以我不会这么快就排除这种可能性。我不喜欢自己这样做,但它不会“打破”模式。事实上,大约十年前我开发了类似于 MVP 的东西,因为我不喜欢 MVC 组件的“循环循环”(查看了解模型);我更喜欢所有这些模式(包括 MVC)所声称的视图和模型的更清晰的分离,以及保持视图尽可能愚蠢的愿望(观察模型将意味着视图需要更多的智能来处理模型更改)。我最终做的是类似于 MVVM 和策略模式的东西,我使用模型的“子结构”传递给视图,充当“更改通知器”。

于 2012-07-16T03:26:01.177 回答