INotifyPropertyChanged (INPC) 应该永远在模型中,除非模型也是 ViewModel(即您没有“模型”)。 INPC 应该只在视图模型中。
模型应该对视图模型一无所知,因此可以永远与它通信。只有视图模型可以与模型通信。
从 UI 的角度来看,只有视图模型对数据做任何事情;所以,如果你希望模型是“只读的”,那么就不要在视图模型中实现它。
绑定将通过视图模型完成,在这种情况下不要使用字典(除非您想编写代码来包装它以便绑定它)。如果 Dictionary 在模型中,那么您应该在视图模型中“包装”它——围绕集合编写一个可观察的包装器是相当简单的。您的视图模型很可能不会处理键/值对——它应该处理 UI 可以处理(并绑定到)的平面。
更新:
INPC 被引入用于数据绑定。它将视图与特定的具体类解耦,因此它只需要了解 INPC(注意解耦的方向)。就 MVVM 而言,这将视图与视图模型解耦,在 PM 的情况下,这可以将视图与演示者解耦,在 MVC 的情况下,这可以将视图与控制器解耦,在 MVP 的情况下,这可以解耦来自演示者的观点。
数据绑定是一种将数据绑定到 UI 元素的技术。它将一个数据源绑定到一个目标,以便目标可以请求数据,无论它认为合适,或者源可以推送数据,但它认为合适(取决于type 绑定——它可以是单向的或静态的,限制 get/push 发生的频率)。
有时,数据源和目标之间解耦关系的必要性质导致人们相信数据绑定不是 UI 问题,数据绑定可以应用于任何地方。即数据绑定实现与 UI 完全分离。这通常是一个错误。数据绑定将视图与特定类的特定知识解耦(这是基本的分层和避免循环,我不会在这里讨论)。但是,它并没有将视图与数据源完全分离。没有数据源就无法进行绑定——那里仍然存在一定程度的耦合,只是缓解了编译时耦合(有助于测试、灵活性、健壮性等,但必须在运行时出现在 production。即 INPC 实现可以在运行时不绑定到 UI 元素的情况下进行测试这一事实并不意味着它不依赖于 UI 框架)。视图仍然与数据源松散耦合的事实并不是这种关系中唯一的耦合。数据源通过其 UI 框架松散地(如果不是不那么松散地)耦合到视图。
每个 UI 框架都有一个限制,即 UI 元素的访问和修改必须在主线程或 UI 线程上完成。 (至少在 Windows 上;它可能发生在其他平台上,我只是不精通其他平台)。使用数据绑定,源间接绑定到控件,任何数据更改都会直接更改一个或多个 UI 元素(取决于您可以拥有中介的框架。就像 WinRT 中的 值转换器,但它们的职责是转换或转换数据)。这意味着数据源需要了解它 绑定到 UI 以及它绑定到的 UI 框架的类型。这种与 UI 框架的紧密耦合显然将数据源(仍然松散)耦合到 UI。
这意味着 INPC 的任何特定实现都真正绑定到一个且只有一个 UI 框架。该对象不能再在 anywhere 中使用(显然 anywhere 是一个理想的选择,通常不可能使任何事情都适用于每个场景——这里的重点是超过只是一两个场景)。例如如果在多线程环境中使用 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 的滥用,并且确实超出了这个问题的重点......