INotifyPropertyChanged
(INPC)永远不应出现在模型中,除非模型也是 ViewModel(即您没有“模型”)。INPC 应该只在视图模型中。
模型应该对视图模型一无所知,因此永远无法与之通信。只有视图模型可以与模型通信。
从 UI 的角度来看,只有视图模型对数据做任何事情;所以,如果你希望模型是“只读的”,那么就不要在视图模型中实现它。
绑定将使用视图模型完成,在这种情况下不要使用 Dictionary(除非您想编写代码来包装它以便绑定它)。如果 Dictionary 在模型中,那么您应该在视图模型中“包装”它——围绕集合编写一个可观察的包装器是相当简单的。您的视图模型很可能不会处理键/值对——它应该处理 UI 可以处理(并绑定到)的平面。
更新:
为数据绑定引入了 INPC。它将视图与特定的具体类解耦,因此它只需要了解 INPC(注意解耦的方向)。就 MVVM 而言,这将视图与视图模型解耦,在 PM 的情况下,这可以将视图与演示者解耦,在 MVC 的情况下,这可以将视图与控制器解耦,在 MVP 的情况下,这可以解耦来自主持人的看法。
数据绑定是一种将数据绑定到 UI 元素的技术。它将数据源绑定到目标,以便目标可以请求数据,无论它认为合适,或者源可以推送数据,但它认为合适(取决于绑定的类型——它可以是单向或静态的,限制如何经常会发生获取/推送)。
有时,数据源和目标之间解耦关系的必要性质导致人们相信数据绑定不是 UI 问题,数据绑定可以应用于任何地方。即数据绑定实现与 UI 完全分离。这通常是一个错误。数据绑定将视图与特定类的特定知识解耦(这是基本的分层和避免循环,我不会在这里讨论)。但是,它并没有将视图与数据源完全分离。没有数据源就无法进行绑定——那里仍然存在一定程度的耦合,只是已经减轻了编译时耦合(有助于测试、灵活性、健壮性等,但必须在生产运行时存在. 即,可以在运行时不绑定到 UI 元素的情况下测试 INPC 实现这一事实并不意味着它不依赖于 UI 框架)。视图仍然与数据源松散耦合的事实并不是这种关系中唯一的耦合。数据源通过其 UI 框架松散地(如果不是更松散地)耦合到视图。
每个 UI 框架都有一个限制,即 UI 元素的访问和修改必须在主线程或 UI 线程上完成。(至少在 Windows 上;它可能发生在其他平台上,我只是不精通其他平台)。使用数据绑定,源间接绑定到控件,任何数据更改都会直接更改一个或多个 UI 元素(取决于您可以拥有中介的框架。就像WinRT 中的值转换器,但它们的职责是转换或转换数据)。这意味着数据源需要深入了解它绑定到 UI 以及绑定到什么类型的 UI 框架。这种与 UI 框架的紧密耦合显然将数据源(仍然松散)耦合到 UI。
这意味着 INPC 的任何特定实现都真正绑定到一个且只有一个 UI 框架。该对象不能再在任何地方使用(显然在任何地方都是理想的,通常不可能使任何东西适用于每个场景——这里的重点是在不止一个或两个场景中的高内聚性)。例如,如果在多线程环境中使用 INPC 的实现,那么它需要在发送属性通知之前将数据“编组”回 UI 线程。在 WinForms 中,即 . Control.BeginInvoke
,在 WPF 和 Silverlight 中,通过System.Windows.Threading.Dispatcher
. 在 WinRT 中,这是通过Windows.UI.CoreDispatcher
. 在所有情况下,INPC 实现都必须直接耦合到一个 UI 框架。在 Silverlight 的情况下,这是与“桌面”的直接耦合Dispatcher
或 Windows Phone Dispatcher
。
质量指标包括凝聚力等概念。内聚度是衡量两个代码单元相关程度的指标。由于支持特定 UI 框架所需的所有基础设施的性质,由 UI 以外的其他东西使用的 INPC 实现,虽然可能能够在 UI 之外使用,但内聚性较低,因为所有不会使用与 UI 框架相关的代码。即,与 UI 完全分离需要承担太多责任。是的,您可以在任何地方使用实现 INPC 的对象并且从不使用该PropertyChanged
事件,但是您的凝聚力很低(被认为是不好的)。
如果我在我的模型中实现了 INPC,并且我想将该模型与我的 UI 和我的 WCF 或 Web 服务后端一起使用,我要么不能,要么我的后端将不得不参考一些 UI 框架。如果我想在另一种类型的 UI 中使用该模型,我不能,因为 INPC 实现依赖于一个特定的 UI 框架。我不得不写另一个“模型”;在这一点上,它显然是一个“视图模型”。
INPC 本身并不绑定到特定的 UI 框架(也不应该如此)。这导致了一种误解,即 INPC 可以在任何地方使用。 是的,它缺乏与高级命名空间的耦合意味着它可以,但是 INPC 的压倒性使用是当目标是 UI 时。我会挑战 INPC 的任何其他不涉及 UI 作为真正“绑定”的用途。与任何其他工具一样,您可以滥用它来获得有用的结果。INPC可用于投影数据,可用于转换数据等;但我相信这些是对 INPC 的滥用,并且确实超出了这个问题的重点......