2013-08-28 50 views
7

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

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

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

b)视图模型现在通过一堆只依照惯例调整的字符串(即没有定义“接口”)耦合到我的模型。更不用说这会导致IDE的困难。

c)我的模型必须修改以适应这种情况!如果由于某种原因关闭了会怎样?我认为这样的模式是为了提高代码的可重用性而设计的。不仅如此,启动INPC事件所需的代码是单调乏味且重复的,并且不是真正可抽象的。

我真的很想知道WPF专业人员是如何通过依赖属性等来解决这个问题的。我感觉我错过了一些东西。我不喜欢使用框架,因为他们想从头开始学习。 我已经离开WPF一两年了,最近和AngularJS合作让我质疑我的方法。

谢谢!

+0

当你说'模型'时,你指的是什么?您是指业务对象/数据类型类,与数据源连接的代码,还是两者? – Sheridan

+0

我指的是业务数据和功能。 在这种情况下,我的模型类是使用VM“TestViewModel”“TestPlanViewModel”的“Test”(属性如“Description”,“Result”,方法如“Run”)和“TestPlan”。 –

+0

您的模型不需要INPC,只需要您的视图模型。这就是你的虚拟机的全部内容 - 我看到有人把INPC放在他们的模型中,但它让我觉得它只是一个视图模型,而不是一个模型。 –

回答

5

出于此答案的目的,我将调用业务对象类的数据类型。

在我个人的经验,视图模型是总是绑的数据类型。您必须具有要显示的类型的属性,因此总是会有一个从视图模型名称空间到数据类型名称空间的引用。

你称为模型(从你的评论中的描述)听起来就像我的视图模型。我的视图模型具有属性,主要是各种数据类型类和方法的类型,而我的数据类型类只是大部分属性......它们只是数据的持有者和变化的记录者。

你似乎觉得INotifyPropertyChanged界面在你称之为'模型'和视图模型类之间执行一些职责...在我看来,这是可选的最好...从INotifyPropertyChanged Interface MSDN上的页面:

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

所以,我看到了INotifyPropertyChanged接口作为是“生命线”的意见和视图模型和数据对象之间去。一些开发人员更喜欢在自己的视图模型中“包装”每种数据类型,但我更愿意直接在我的数据类型中实现接口。

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

它还为每个数据类型类创建匹配视图模型类节省了时间。为什么有两个班级要做什么?我从来不需要这种分离的程度。如果我正确地理解了你,在你的数据类型类中实现这个接口将否定执行你的观点a)的必要性。

你的一些点B)和C)可以也将成为无效的,如果你可以使用.NET 4.5的有一个新的CallerMemberNameAttribute属性,你可以用它来自动进给每个属性的名称为PropertyChanged处理器。我发现了一篇名为C# 5–Making INotifyPropertyChanged Easier的好文章,并对其进行了很好的描述。

我已经写了几个大规模的WPF应用程序,现在和几个框架,我从来没有遇到过在我的数据类型类中实现接口INotifyPropertyChanged的问题。事实上,如果我必须为每个数据类型类实现包装视图模型类,我不认为我可以在同一时间写入它们。迄今为止,这种方法已经很好地发挥了作用,并且我计划继续使用它,直到我找到更好的方法。然而,这仅仅是一个开发者的意见,你必须选择适合自己的东西。

+0

很好的答案,感谢您花时间写下来。 我是否正确地解释你说你的视图模型公开你的模型类的实例(又称数据类型本身是通告器),而不是单独的视图模型代理每个属性? 我对MVVM的理解是模拟屏幕上显示的数据。你可以在每个模型类/数据类型或每个VIEW基础上做到这一点,我认为后者符合你的建议? –