MVVM:ViewModel和业务逻辑连接

JDe*_*ker 42 c# wpf design-patterns mvvm

在使用MVVM模式执行一些项目之后,我仍然在努力使用ViewModel的角色:

我过去做了什么:仅将模型用作数据容器.使逻辑操纵ViewModel中的数据.(这就是业务逻辑吗?)Con:逻辑不可重复使用.

我现在正在尝试:保持ViewModel尽可能薄.将所有逻辑移动到模型层.仅在ViewModel中保留演示逻辑.Con:如果在模型层内更改了数据,则会使UI通知真的很痛苦.

所以我会给你一个例子,让它更清晰:

场景:重命名文件的工具.类:文件:代表每个文件; 规则:包含逻辑如何重命名文件;

如果我遵循方法1:为文件,规则和视图创建ViewModel - > RenamerViewModel.将所有Logic放在RenamerViewModel中:包含FileViewModel和RuleViewModel的列表以及正在进行的逻辑.简单快速,但不可重复使用.

如果我遵循方法2:创建一个新的模型类 - >重命名,其中包含文件列表,规则和进行逻辑以对每个文件进行交互并应用每个规则.为文件,规则和重命名器创建视图模型.现在RenamerViewModel只包含一个Renamer Model的实例,加上两个ObservableCollections来包装Renamer的File和Rule List.但整个逻辑都在Renamer模型中.因此,如果触发重命名模型以通过方法调用操作某些数据,则ViewModel不知道哪些数据被操纵.因为模型不包含任何PropertyChange通知,我会避免这种情况.因此,业务和表示逻辑是分开的,但这使得很难通知用户界面.

Jon*_*Jon 51

将业务逻辑放在viewmodel中是一种非常糟糕的做事方式,所以我很快就会说从来没有这样做,继续讨论第二种选择.

将逻辑放在模型中更合理,这是一个很好的启动方法.有什么缺点?你的问题说

因此,如果触发重命名模型以通过方法调用操作某些数据,则ViewModel不知道哪些数据被操纵.因为模型不包含任何PropertyChange通知,我会避免这种情况.

好吧,制作模型工具INotifyPropertyChanged肯定会让你继续前进到更好的事情.但是,有时候不可能这样做 - 例如,模型可能是一个部分类,其中属性由工具自动生成,不会引发更改通知.这是不幸的,但不是世界末日.

如果你想买东西,那么有人必须付钱; 如果它不是提供此类通知的模型,那么您只剩下两个选择:

  1. 视图模型知道模型上的哪些操作(可能)导致更改,并在每次此类操作后更新其状态.
  2. 其他人知道哪些操作会导致更改,并且它们会在包装更改的模型之后通知viewmodel更新其状态.

第一个选项也是一个坏主意,因为实际上它将回到将"业务逻辑"放在视图模型中.没有将所有业务逻辑放在viewmodel中那么糟糕,但仍然如此.

第二种选择更有希望(不幸的是,更多的工作要实施):

  • 将您的业务逻辑的一部分放在一个单独的类("服务")中.该服务将通过适当处理模型实例来实现您希望执行的所有业务操作.
  • 这意味着服务知道模型属性何时可能发生变化(这没关系:模型+服务==业务逻辑).
  • 该服务将向所有相关方提供有关已更改模型的通知; 您的视图模型将依赖于服务并接收这些通知(因此他们将知道"他们的"模型何时更新).
  • 由于业务操作也由服务实现,因此这仍然非常自然(例如,当在视图模型上调用命令时,反应在服务上调用适当的方法;记住,视图模型本身不知道业务逻辑).

有关此类实现的更多信息,请参阅此处此处的答案.

  • 通知总是被描述为 ViewModel 部分,这就是为什么我会在模型中避免它。感觉就像同一件事做了两次。 (2认同)

Ken*_*art 12

这两种方法都是有效的,但还有第三种方法:在模型和VM层之间实现服务.如果您想让模型保持愚蠢,服务可以提供与UI无关的中间人,可以以可重复使用的方式强制执行您的业务规则.

因为模型不包含任何PropertyChange通知,我会避免这种情况

你为什么要避免这个?不要误解我的意思,我倾向于让我的模型尽可能保持愚蠢,但在模型中实现更改通知有时会很有用,而且只在System.ComponentModel你做的时候依赖.它完全与UI无关.


rol*_*lls 5

我执行以下操作

  1. 仅使用 XAML 视图逻辑进行视图

  2. ViewModel 处理点击处理程序并创建新的视图模型。处理路由事件等。

  3. 模型是我的数据容器和有关验证模型数据的业务逻辑。

  4. 用数据填充模型的服务。例如,调用 Web 服务器,从磁盘加载它,保存到磁盘等。根据示例,我的模型和服务通常都会实现 IPropertyChanged。或者他们可能有事件处理程序。

在我看来,任何复杂的应用程序都需要另一层。我称之为模型+服务、视图、视图模型。该服务抽象您的业务逻辑,并将模型实例作为依赖项或创建模型。