WPF 的综合指南:MVVM 与 MVP

Posted

技术标签:

【中文标题】WPF 的综合指南:MVVM 与 MVP【英文标题】:Composite Guidance for WPF : MVVM vs MVP 【发布时间】:2010-10-24 18:11:50 【问题描述】:

我很困惑。也许你可以帮助我:)

我一直遵循 CAG 的指导,发现 MVP 模式对我来说非常自然。 假设我有一个 UI 就绪模型(例如:实现 INotifyPropertyChanged),我使用演示者将此模型绑定到视图(演示者知道视图的接口),使我的代码隐藏尽可能小,仅处理绑定(模型和命令)属性(或方法)或没有 ICommand 的控件的事件,在这种情况下立即委托给演示者。

    一段时间后,我发现了 MVVM 模式,但到目前为止我还没有发现它。 据我所知,我只会在我的模型未准备好 UI 时使用 MVVM。但是保留演示者并只使用新模型是否更合理,我不明白这种用法会失去什么。 我知道我错过了什么,但它是什么:)。

    当您的视图是通用的并且可以处理多种模型(例如在 PropertyGrid 中)时。建议 ViewModel 与 DataTemplate 一起使用,但在这种情况下,您无法为模型中的每个实体创建模板,只需要在运行时进行调查,您会推荐什么?

    在看 Josh Smith 在screencast 中谈论 MVVM 时,我有一种感觉,在 ViewModel 中重新暴露 Model 违反了 DRY(不要重复自己),真的无法避免吗?与火焰相比,没有人对此争论不休,这让我感到惊讶ADO.Net Dynamic Data metadata classes are getting nowadays。

希望它足够清楚

谢谢

爱丽儿

【问题讨论】:

【参考方案1】:

广告 3。您似乎在重复自己在 ViewModel 中公开 Model,但实际上您所做的是抽象 Model,以便 View 只知道这个抽象(View 只知道 ViewModel)。

这是因为对模型的更改不应破坏视图。此外,您的模型可以实现为从不同来源获取数据的许多不同服务。在这种情况下,您不希望 View 知道所有这些,因此您创建另一个抽象 - ViewModel。

【讨论】:

【参考方案2】:

关于#3,很多人会使用“另一层间接”的说法,说模型的变化不会影响视图。虽然这在技术上是正确的,但这并不是这样做的真正原因。

如果您将模型视为您从数据访问层或服务(通常被认为是这些)返回的实体,您就会开始明白为什么需要 ViewModel。 ViewModel 旨在使用 View 需要的行为扩展模型

例如。如果您希望能够更改属性并通过绑定通知视图此更改,则该属性需要引发某种形式的 NotifyPropertyChanged 以便视图可以做出反应。这是典型模型所没有的行为。

在另一个示例中,假设您有一个集合,并且您希望在用户单击视图中该项目旁边的复选标记时使用布尔值标记该集合中的每个项目。您可能需要一个“IsSelected”属性。这是模型不应该提供的行为。

但是我知道你来自哪里......我一开始肯定有这个问题。我第一次将模型的内容复制并粘贴到我的视图模型中时,我的胃转了,但你只需要接受这样一个事实,即要让视图工作,它需要模型应该有的这种额外行为不提供。

无论这有多不干,强制您的 WCF 类型或 LINQ to SQL 类型(或任何您喜欢的 ORM)来实现 INotifyProperyChanged 会更糟。

【讨论】:

+1 总体上很好的答案,但最后一句话真的很重要。 在我们的 MVVM 实现中,我们仍然使用领域驱动设计影响编写模型,以及从业务对象框架(例如已经实现 INotifyProperyChanged 的​​ CSLA)中学到的一些东西。到目前为止,由于我们的设计,我们的 ViewModel 中的 Model 重复次数要少得多,并且通常只需要在 Anderson 提到的需要对 View 进行不同的抽象事物时编写相应的 ViewModel 类。【参考方案3】:

除了上面的cmets。我想分享一些我个人对差异的理解。

通常在 MVP 中你有一个 View 接口,例如。 IView,用于抽象实际视图并将数据绑定到这些实际视图。相反,在 MVVM 中,您通常使用实际视图的 DataContext,例如。一个 XAML 用户控件,用于进行数据绑定,类似于 MVP 中的 IView。因此,不准确地说,两种模式的绑定是相似的。

主要区别在于 Presenter 与 ViewModel 部分。视图模型与演示者非常不同,演示者是 UI 和模型之间交换数据的桥梁。实际上,正如它的名字一样,它是视图的模型。 ViewModel 中暴露的数据主要用于 UI 流程。所以据我了解,在 MVVM 中,ViewModel 是视图的抽象。与之相反,MVP 主要使用 IView 来抽象视图。所以通常 MVVM 中的层数比 MVP 少,因此您可以编写更少的代码来在 MVVM 中完成相同的工作:

MVVM: Model - ViewModel(代表实际视图,即UI) - Actual Views

MVP:Model - Presenter(模型和UI之间交换数据的桥梁)- IView(代表实际视图,即UI)- Actual Views

MVVM 相对于 MVP 的优势主要基于 Microsoft 产品中的以下 2 个强大功能,

    WPF 中的命令。尽管已经有一些实现不在 Silverlight 运行时中,但它可能会在未来的 Silverlight 中可用

    WPF 和 Silverlight 中的 DataContext。

【讨论】:

【参考方案4】:

如果演示者知道视图的界面,您要么需要演示者使用的所有视图具有相同的界面,要么为每个视图创建一个演示者。使用 MVVM,视图知道 viewModel,而 viewModel 知道模型(反之亦然)。这意味着多个视图可以使用一个 VM,多个 VM 可以使用一个模型。

我不太确定您在第二点中要问什么。 VM 不是视图(或不知道视图),对我而言,DataTemplate 定义了对象的显示方式。我将我的 DataTemplates 放在绝对属于视图的 ResourceDictionary 中。我的 VM 层中唯一的 WPF“东西”是命令。

我需要更多信息来回答您的第三点。如果您深入了解 MVVM,也许它会自行解决。

Here's a related post of mine which might help you

祝你好运。

【讨论】:

以上是关于WPF 的综合指南:MVVM 与 MVP的主要内容,如果未能解决你的问题,请参考以下文章

浅谈开发中的MVVM模式及与MVP和MVC的区别

EDA与特征工程数据探索与特征工程综合指南

WPF 布局之综合实例

WPF--3Dmax+blend+WPF综合运用

mvc mvp mvvm的区别

WPF--3Dmax+blend+WPF综合运用