如何将模型中的更改传递到模型视图?

3

我目前正在忙于将一个应用程序逐步重写为MVVM(因为这是一项艰巨的工作)。

目前,我可以根据模型视图中的更改填充列表视图和控件,并且列表视图选择正确地耦合(至少我知道如何正确地做到这一点)。

然而,我想知道模型中的更改是否会反映在模型视图中(从而反映在视图中)。我是否需要在模型中的所有项目上添加INotifyPropertyChange接口,并在模型视图上订阅(甚至像链一样订阅不在模型层次结构“顶部”的项目)?

例如,我有一个包含列表B等列表A的列表。我需要在列表A中订阅列表B的属性更改,并在模型视图中订阅列表A吗?如果进行其他列表选择(导致大量取消订阅和新订阅项),则需要取消订阅吗?

感谢您的阅读/回答。


你能提供一点示例代码作为背景吗? - Erik Dietrich
2个回答

6

通常情况下,您应该在模型上实现INotifyPropertyChanged,并在视图模型中订阅。如果您正在使用诸如CSLA之类的框架来处理业务实体,则Rocky描述了贫血模型与丰富模型之间的区别,在后者中,您将模型直接作为属性公开到视图中。

我认为INotifyPropertyChanged是稳定的依赖项,因此不会显著污染您的模型。有些人不喜欢直接将模型公开到视图中,但我发现这样可以节省很多重复的代码。您可能会发现,如果不这样做,您的视图模型最终会复制模型上的许多属性,而不添加任何价值。


谢谢您的回答。我也不认为INotifyPropertyChanged实现会污染我的模型。然而,我需要将它们放在ViewModel中(我认为这比放在视图本身中更好),或者我误解了您的意思?此外,我需要复制我在ModelView中需要的属性,因为我无法将它们连接到模型中的任何地方。 - Michel Keijzers
我不确定我理解你的意思。您将在模型和视图模型上实现INotifyPropertyChanged。如果您希望将模型暴露给视图,则您的视图模型将具有YourModel类型的Model属性。您的视图模型还可以具有其他属性,以将模型数据塑形为视图。例如,您的视图模型可能具有一个Age属性,而您的模型只有一个DateOfBirth属性。视图不会实现INotifyPropertyChanged,但会订阅PropertyChanged事件(这是使用XAML绑定引擎自动完成的)。 - devdigital
好的,我想我们的意思是一样的。如果我理解得对,我需要在我的 ModelView 中放置一个 PropertyChanged 方法,并且它应该监听模型。它们会监听模型的各个部分并设置通过 XAML 相关联的属性。 - Michel Keijzers
昨天我继续做我的应用程序一会儿,但在我尝试这个解决方案之前,我需要修复几个问题(这个解决方案可能有效,但我还不能实现它)。我会在完成实现这个解决方案后立即回应。 - Michel Keijzers

2

如果我理解正确,您希望以编程方式更改模型中的数据,并通过视图模型相应地显示更新后的数据?

我建议您在代码中更改视图模型属性,只使用模型来加载/保存数据,这将消除该问题。


谢谢回答。在模型内部更改数据是否很奇怪?这是在ViewModel中完成的,但是模型随后会发生变化,我想我必须订阅模型内部的更改。因此,当通过ViewModel更改模型时,我希望(相同的)ViewModel侦听模型中的更改,以反映其在窗口中的更改(与该ViewModel连接)。 - Michel Keijzers
我不太理解这个问题:当你自己实现属性的getter/setter来将属性映射到模型属性时,例如 get { return _model.MyProperty; } set { _model.MyProperty = value; OnPropertyChanged("MyProperty"); },你会得到GUI和模型的更新。除了在反映模型属性的视图模型属性中,你永远不需要在代码中访问模型属性... - eFloh
我理解那部分内容,但如果模型被更改并且我想在ModelView中得到通知,我需要订阅模型中各个位置的许多项,这些项也需要在例如在listview上进行新选择时取消订阅。也许我应该添加一些代码,但我担心它会太多,没有人会花时间去阅读它。 - Michel Keijzers
无论什么能澄清问题都会有所帮助。您还可以给出一个精确的工作流程示例。 - eFloh
我会在尝试我接受的解决方案后(它可能有效)给出一个例子。或者至少部分地尝试,但此时我需要找时间来实现它。我稍后会编辑我的问题(如果它有效的话)。 - Michel Keijzers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接