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 的滥用,并且确实超出了这个问题的重点......