我正试图了解MVVM并且不知道如何建模以下内容。
假设一个实体包含零到多个其他实体的现实情况。
在MVVM中,模型可以是类A,例如作为成员具有类C的对象列表ListOfC。例如(没有构造函数代码等):
b.takeEvery(1000).forEach(t => console.log(t))
现在我如何获得一个视图模型,该视图模型将通知视图所有对数据的更改?
我可以构建一个实现INotifyPropertyChanged的类AVM,没问题。由于ListOfC被定义为ObservableCollection,如果我更改列表,我会收到通知。 然后我可以创建一个实现INotifyPropertyChanged的类CVM,例如(没有通知代码,构造函数等):
<wait 1s>
2
<wait 1s>
4
<wait 1s>
6
我想要实现的是当更改名称或启用C时,UI会显示更改。我所拥有的是一个列表视图,它绑定到A列表并显示所有项目(工作),第二个列表视图,第一个列表视图中的每个选定项目应该显示一个C列表,其中包含Name和Enabled的值。当第一个列表的选择发生更改时,此列表会显示并更新,但如果从后端更改了“名称”或“已启用”,则不会更新第二个列表。
如何从模型中的A到C关系到视图模型中的AVM到CVM关系,而不实际维护A中的C列表和AVM中需要保持同步的CVM列表?当然有一种更简单的方法吗?如果你知道我的意思,那就好像我想把A中的ListOfC“转换”成AVM中的ListOfCVM一样......
答案 0 :(得分:2)
MVVM是一种用于分离开发的软件架构模式。
每个维基百科:
模型指的是代表真实状态内容的领域模型(面向对象的方法),或代表内容的数据访问层(以数据为中心的方法)。
与MVC和MVP模式一样,视图是用户在屏幕(UI)上看到的结构,布局和外观。
视图模型是公开属性和命令的视图的抽象。 MVVM不是MVC模式的控制器,也不是MVP模式的演示者,而是有一个绑定器。在视图模型中,绑定器调解视图和数据绑定器之间的通信。[需要澄清]视图模型已被描述为模型中数据的状态。
简而言之:
通常,每个View
(xaml文件)都有一个关联的ViewModel
(cs文件)。原因是因为ViewModel
将处理其关联的View
的逻辑,而不是使View
执行幕后的运算(xaml.cs文件)。这样做的好处是1.它对View
本身的影响较小,而且2.开发分离,这使得测试特定组件等更容易。
MVVM的整个概念围绕着数据绑定的思想。换句话说,如前所述,每个View
都有其关联的ViewModel
。它与ViewModel
绑定(ViewModel
设置为DataContext
的{{1}}),以便View
可以进行嘎吱嘎吱。
以下是帮助您掌握概念的示例:
您的应用程序有一个
ViewModel
,而View
只包含一个文本框和一个按钮。用户可以在文本框中输入文本,并且当按下按钮时,文本在文本框内改变以从输入的文本中移除所有元音。因此,如果用户输入&#34; hello world!&#34;并按下按钮,文本框将从&#34; hello world改变!&#34; to&#34; hll wrld!&#34;在幕后,发生的事情是
View
有一个名为MyText的属性,它是一个字符串。当用户在文本框中输入(在ViewModel
中)时,属性(在View
中)会相应地更改。当用户按下按钮时,挂钩到按钮ViewModel
(在ViewModel
中)的处理程序方法(在Click
中)将会显示MyText属性并执行元音删除。一旦MyText属性的值从&#34; hello world改变了!&#34; to&#34; hll wrld!&#34;View
中的文本框会自动反映此更改,因为绑定将是双向绑定。
为了实现这样的绑定,文本框的View
代码(xaml)看起来像:
View
和其他地方(在<TextBox Name="Mytextbox" Text="{Binding Path=MyText, Mode=TwoWay}" />
xaml或View
xaml.cs(幕后)中,将设置DataContext:
View
我希望这有助于消除您的困惑,并希望您可以将这些概念应用于您试图包围的特定应用程序。
答案 1 :(得分:1)
正如MickyD在评论中所说,模型类应该实现INotifyPropertyChanged
。该模型仅仅是因为模型不应该获得任何特定于用例或特定于用户任务的行为或应用程序逻辑以获得最佳可重用性。 This article from msdn对MVVM模式中的类职责和特征进行了详尽的讨论。也许它会帮助你更好地理解MVVM。
答案 2 :(得分:0)
我想要实现的是当更改名称或启用C时,UI会显示更改
为此,后端或模型必须通知外部世界。最常见的方法是引发事件,例如PropertyChanged
接口的INotifyPropertyChanged
事件。
如果模型在修改状态时没有引发任何事件,那么其他人(例如视图模型或视图)查明其是否实际被修改的唯一方法是检查模型属性的值,并将它们与常规(轮询)间隔的最新已知值进行比较。与听取事件相比,这是一个难看的解决方案。
所以在这种情况下,听起来你的模型类应该实现INotifyPropertyChanged
接口。如果它们提供任何其他方式来通知观察者其状态已更改,则需要将模型类包装在实现INotifyPropertyChanged
接口的视图模型类中,并绑定到客户端应用程序中的这些视图模型类。这是因为WPF只知道如何为实现此特定接口的对象订阅属性(状态)更改。
希望这是有道理的。
答案 3 :(得分:0)
有几种方法可以确保V和M保持同步:
M实现了INotifyPropertyChanged - 如上所述,这允许VM将类从M直接暴露给V;否则,VM必须订阅M的PropertyChanged事件并为V生成自己的PropertyChanged事件。
VM知道M何时发生变化 - 这对于拥有M实例的唯一所有权的编辑者尤为重要。在这种情况下,VM对M执行的每个操作都必须提高相应的PropertyChanged events。
通过其他事件/通知处理对M的更改。一个例子是对M中A类给定属性B的所有更改都是由单个类BofAUpdater执行的,它会在A的任何实例上更改B时发送通知。根据情况,这可以减少订阅任务所有必需的事件/通知。