MVVM 模式中有三个核心组件:模型、视图和视图模型。 每个组件的用途不同。 下图显示了这三个组件之间的关系。
在交互层次上,视图“了解”视图模型,视图模型“了解”模型,但模型不知道视图模型,而视图模型不知道视图。 因此,视图模型将视图与模型隔离开来,并允许模型独立于视图进行演变。
使用 MVVM 模式的好处如下:
- 模型实现封装了业务逻辑,更改它可能很困难或有风险。 在此场景中,视图模型充当模型类的适配器,并阻止你对模型代码进行重大更改。
- 可以在不使用视图的情况下为视图模型和模型创建单元测试。 视图模型的单元测试可以执行与视图使用的完全相同的功能。
- 无需接触视图模型和模型代码即可重新设计应用 UI。 因此,新版本的视图应与现有视图模型一起使用。
- 设计人员可以专注于视图,而开发人员可以处理视图模型和模型组件。
有效使用 MVVM 的关键在于了解如何将应用代码分解为正确的类以及这些类的交互方式。 下面几节讨论 MVVM 模式中每个类的责任。
view
View(视图)负责定义用户在屏幕上看到的结构(structure)、布局(layout)和外观(appearance)。理想情况下,视图完全使用QML/XAML定义,包含很少(受限制)的后台代码,不包含业务逻辑。
在应用程序中,视图通常是一个页面。此外,视图也可以是父视图的子组件。
视图可以有自己的视图模型,也可以继承其父视图模型。视图通过绑定或调用视图模型上的方法从视图模型获取数据。在运行时,当UI控件响应引发更改通知事件的视图模型属性时,视图将发生更改。
Model
MVVM中的Model(模型)是应用程序领域模型的实现,它包括数据模型以及业务和验证逻辑。模型对象的示例包括存储库、业务对象、数据传输对象(dto)、以及生成的实体和代理对象。
ViewModel
ViewModel(视图模型)充当视图和模型之间的中介,并负责处理视图逻辑。通常,视图模型通过调用模型类中的方法与模型进行交互。
viewModel可以很容易的使用Model中的数据。视图模型从模型中检索数据,然后使数据对视图可用,并可能以某种方式重新格式化数据,使视图更容易处理。
viewModel还提供了应用程序用户在视图中发起的命令的实现。例如,当用户单击UI中的按钮时,该操作可以触发视图模型中的命令。视图模型还可能负责定义影响视图中显示的某些方面的逻辑状态更改,例如指示某些操作正在挂起。
为了使视图模型参与与视图的双向数据绑定,其属性必须引发PropertyChanged事件。
使用MVVM模式,应用程序的UI以及底层的表示和业务逻辑被分为三个独立的类:
视图:它封装了UI和UI逻辑;
视图模型:它封装了表示逻辑和状态;
模型:封装应用程序的业务逻辑和数据。
类的职责和特点
MVVM类及其交互
与所有分离的表示模式一样,有效使用MVVM模式的关键在于理解将应用程序代码分解为正确类的适当方法,以及理解这些类在各种场景中的交互方式。
视图还是视图模型?
很多时候,确定某个功能应该在哪里实现并不明显。一般的经验法则是:任何与屏幕上UI的特定视觉外观有关的东西,以及以后可能被重新设计的东西(即使你目前不打算重新设计它)都应该进入视图;任何对应用程序的逻辑行为很重要的东西都应该放到视图模型中。此外,由于视图模型不应该明确了
解视图中特定的可视元素,因此以编程方式操作视图中可视元素的代码应该驻留在视图的代码后面,或者封装在行为中。类似地,检索或操作通过数据绑定在视图中显示的数据项的代码应该驻留在视图模型中。
例如,列表框中选中项目的高亮颜色应该在视图中定义,但是要显示的项目列表以及对选中项目本身的引用应该由视图模型定义。
模型封装了业务逻辑和数据。
什么是业务逻辑?业务逻辑被定义为与应用程序数据的检索和管理有关的任何应用程序逻辑,并用于确保数据一致性和有效性的任何业务规则。
为了最大化重用机会,模型应该具备以下特点:
模型不应该包含任何特定于用例;
模型不应该特定于用户任务或行为;
模型不应该特定于应用程序逻辑。
如果您的模型类没有实现所需的接口怎么办?
有时,您将需要处理不实现INotifyPropertyChanged、INotifyCollectionChanged、IDataErrorInfo或INotifyDataErrorInfo接口的模型对象。在这些情况下,视图模型可能需要包装模型对象并向视图公开所需的属性。这些属性的值将由模型对象直接提供。视图模型将为它所公开的属性实现所需的接
口,以便视图可以轻松地与它们进行数据绑定。
总结:
模型类是封装应用程序数据和业务逻辑的非可视化类。它们负责管理应用程序的数据,并通过封装所需的业务规则和数据验证逻辑来确保数据的一致性和有效性。
模型类不直接引用视图或视图模型类,也不依赖于它们的实现方式。
模型类通常与封装数据访问和缓存的服务或存储库一起使用。