14

我在尝试了解一些 MVP 内容时获得了一些乐趣,因为它与用户控件有关。我正在使用.NET WinForms(或类似的东西)和监督控制器模式(嗯,我想我是:)。

用户控件本身就是 MVP 应用程序的一部分(它的视图和相关的演示者等)。Presenter 总是首先启动,它启动模型,然后是视图。View 构建它的 UI,其中一部分将用于 NEW UC,即 View。

现在(表单)Presenter 需要了解 UC Presenter,但我认为它对 View 的组成方式一无所知。例如,表单 Presenter 不知道 UC 是表单控件集合的一部分,也不应该知道。

此外,不应改变设计经验;IOW 视图(表单)的开发人员应该能够从工具箱中选择一个用户控件并将其拖放到表单上。

所以,关于我的问题。首先,我上面的假设是否正确?有点误入歧途?弄乱?你在想什么?

其次,让表单 View 调用 UC View 并且表单 Presenter 调用 UC Presenter 并有一些机制告诉 UC View 它的 Presenter 是正确的(足够吗?)?这违反了我的“演讲者优先”规则,但我不知道该怎么做。

任何其他想法、建议、评论都乐于接受。

--nwahmaet

4

3 回答 3

13

演示者应该被认为是演示层中的“自治状态”。这意味着它负责确保视图对模型状态的表示是同步的。我提出这个的原因是因为 MVP 的“模式”经常迷失在应该如何分离事物的教条观点中。这似乎是 Martin Fowler 决定尝试澄清围绕 MVP模式的术语的原因之一。

我最喜欢的 MVP 风格是被动视图,所以我的回答是基于此。

我经常使用被动视图模式来实现复合用户控件和表单。基本上有3种不同的配置:

  1. 层次结构中所有用户控件的一位演示者。使用界面展平视图。
  2. 复合树中每个用户控件的一个演示者。每个父 Presenter 负责实例化和初始化其子 Presenter。用户控件是在设计时创建的,并且能够在没有演示者的情况下运行(没有演示行为)
  3. 复合树中每个用户控件的一个演示者。所有的演示者都通过更高级别的控制器类松散耦合。控制器类负责构建演示者,将它们连接起来,并协调它们的事件。

尽管它对我来说是最后的解决方案(因为它的复杂性),但我认为最后一个选择是您正在寻找的解决方案。

于 2009-01-15T15:33:19.030 回答
4

在我正在开发的应用程序中,几个月来我一直在遇到这个确切的问题。我最近得出的结论是,在许多情况下,在不“破坏”模式的情况下,可能无法在窗口和用户控制级别应用 MVP 模式。

我的想法是用户控件是视图实现的一部分,演示者不应该知道视图实现内部发生了什么,这意味着扩展的窗口级演示者不应该知道用户控件的演示者,因此它们之间不应该有任何通信,包括前者对后者的实例化。可能有人认为用户控件的演示者是窗口视图实现的一部分,因此窗口视图可以实例化用户控件演示者。但它不能注入演示者需要的模型类,因为视图不应该知道它们。

我认为我得出的结论是所有用户控件都是特定于视图实现的,因此应该完全包含在更大模式的视图筒仓中。因此,他们没有自己的演示者……至少没有与控制实现本身捆绑在一起。相反,它们应该由父窗口的演示者通过在视图界面上公开的传递字段间接操作。简而言之,用户控件不是通过其自己的界面向演示者公开的,而是通过其父视图实现的通用传递接口。将此称为“局部视图界面”。

然后,您的演示者可以包含可重用的子演示者类的实例,该类仅适用于此部分视图界面和模型的相关部分。这将允许您避免在每次需要使用控件时重新编写演示者代码以从模型进行转换,并且它可以防止窗口视图需要了解模型以便将信息传递给控件的演示者。

这有效地做的是它进一步将用户控件作为一个模块从您的数据模型中分离出来。如果您将用户控件作为一个整体视为视图实现的一个元素,那么这是有道理的。作为一个可重用的单元,它是一个视图功能,它的任何部分都不应该与您的数据模型相关联。

于 2009-01-15T01:25:20.897 回答
0

您的问题很笼统,可以应用多种方案。

在这种情况下,我的猜测是您应该查看观察者模式。

你有一个接口,任何使用该视图的东西都可以实现。然后,当应用程序使用这些接口的集合进行初始化时,它会注册自己。任何需要更新该视图的命令都将遍历集合,通知每个视图都应该更新。

与典型示例不同,视图将是用户控件。您可以灵活地使任何 UI 元素实现该界面,因此除了用户控件之外,您还可以使用对话框、完整表单等。

最后记住用户控件不是视图,而是视图的实现。无论您采用哪种方案,您都可以根据需要定义视图的深度,并让用户控件实现该接口。

于 2009-01-09T20:30:11.367 回答