【问题标题】:WPF MVVM: INPC and mediating communication between view model & modelWPF MVVM:视图模型和模型之间的 INPC 和中介通信
【发布时间】:2013-08-31 19:14:19
【问题描述】:

我已经阅读了各种将模型数据更改传达给视图模型的方法。 有人建议模型应该尽可能实现 INotifyPropertyChanged,以便它可以通知视图模型更改的属性。有人建议在模型和视图模型之间建立一个服务层,服务层实现 INPC,方法调用通过该服务层路由到模型,以便服务层通知视图模型。

我认为后者是前者的更细化的修订版,并已开始在我的模型类中实现 INPC。感觉不对,因为

a) 我现在必须在我的视图模型中为来自模型的通知编写一个事件处理程序。 这采用长开关(propertyName)的形式,它在视图模型上设置相应的属性,导致 NPC 再次向上发送。我觉得我在这里写了很多样板代码。

b) 视图模型现在通过一堆字符串耦合到我的模型,这些字符串完全由约定规范,即没有定义“接口”。更不用说这给 IDE 带来的困难了。

c) 我的模型必须修改以适应这种情况!如果由于某种原因关闭了怎么办?我认为这样的模式旨在提高代码的可重用性和关注点的分离。不仅如此,触发 INPC 事件所需的代码也是乏味和重复的,而且不是真正抽象的。

我真的很想知道 WPF 专业人员如何通过依赖属性等来解决这个问题。我觉得我错过了一些东西。我不热衷于使用想要“从头开始”学习的框架。 我已经离开 WPF 一两年了,最近使用 AngularJS 让我质疑我的方法。

谢谢!

【问题讨论】:

  • Model 到底指的是什么?您是指业务对象/数据类型类、与数据源连接的代码,还是两者兼而有之?
  • 我指的是业务数据和功能。在这种情况下,我的模型类是“Test”(属性如“Description”、“Result”,方法如“Run”)和“TestPlan”,VM 为“TestViewModel”“TestPlanViewModel”。
  • 您的模型不需要 INPC,只需要您的视图模型。这就是你的虚拟机的全部意义——我见过人们把 INPC 放在他们的模型中,但我觉得它只是把它变成了一个视图模型,而不是一个模型。
  • +1。我已经为此苦苦挣扎了一段时间,最终我选择了选项a)。它确实是样板代码,但我发现这比打破模块化更可取。我通常发现,在回答这个问题时,人们倾向于说ViewModel 应该检查来自Model 的更新而不是被通知,但是如果我的Model 在后台异步咀嚼,我不会希望不得不坐在那里“轮询”它以获取更新。如果存在更好的解决方案,我很乐意改用更清洁的东西。
  • 您不必在您的虚拟机中使用凌乱的观察者 (This takes the form of a long switch(propertyName))。使用This 之类的东西,你会省去一些麻烦

标签: c# wpf mvvm dependency-properties inotifypropertychanged


【解决方案1】:

为了回答这个问题,我将业务对象类称为“数据类型”。

根据我的个人经验,视图模型总是与数据类型相关联。您必须具有要显示的类型的属性,因此始终存在从视图模型命名空间到数据类型命名空间的引用。

您所说的模型(根据您在评论中的描述)听起来像我的视图模型。我的视图模型具有属性,主要是各种数据类型类和方法的类型,而我的数据类型类大部分只包含属性......它们只是数据的持有者和变化的报告者。

您似乎认为INotifyPropertyChanged 接口在您所称的“模型”和视图模型类之间执行一些职责......在我看来,这充其量是可选的......来自INotifyPropertyChanged Interface MSDN 页面:

INotifyPropertyChanged 接口用于通知客户端(通常是绑定客户端)属性值已更改。

因此,我将INotifyPropertyChanged 接口视为视图 与视图模型和数据对象之间的“生命线”。一些开发人员更喜欢将每种数据类型“包装”在自己的视图模型中,但我更喜欢直接在我的数据类型中实现INotifyPropertyChanged 接口。

我这样做的主要原因是我可以在我拥有的自定义集合类中挂钩到这个框架。这使我能够拥有知道对集合中任何项目中的任何属性所做的任何更改的集合。它还使我能够将数据同步构建到我的基类中,以便对象知道它们何时有任何更改。

它还可以节省为每个数据类型类创建匹配视图模型类的时间。为什么有两个班可以做一个可以做的事?我从来不需要那种程度的分离。如果我理解正确,在您的数据类型类中实现此接口将不需要执行您的观点 a)。

如果您可以使用 .NET 4.5,您的一些观点 b) 和 c) 可能也会被渲染为无效,因为有一个新的 CallerMemberNameAttribute 属性可用于自动提供PropertyChanged 处理程序的每个属性。我找到了一篇名为 C# 5–Making INotifyPropertyChanged Easier 的好文章,其中有很好的描述。

我现在已经编写了几个大型 WPF 应用程序和一些框架,并且在我的数据类型类中实现 INotifyPropertyChanged 接口从来没有遇到过问题。事实上,如果我必须为每个数据类型类实现包装视图模型类,我认为我不可能同时编写它们。到目前为止,这种方法对我很有帮助,我打算坚持下去,直到至少找到更好的方法。然而,这只是一位开发人员的意见,您必须选择适合您的方式。

【讨论】:

  • 哇很好的答案,感谢您抽出宝贵的时间来编写它。我是否正确地解释了您的视图模型公开了模型类的实例,也就是数据类型本身就是通知器,而不是视图模型单独代理每个属性?我对 MVVM 的理解是对屏幕上显示的数据进行建模。您可以在每个模型类/数据类型或每个 VIEW 基础上执行此操作,我认为后者符合您的建议?
猜你喜欢
  • 2020-01-09
  • 2014-07-10
  • 2014-10-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多