MVVM:视图模型和业务逻辑连接(MVVM: ViewModel and Business Logi

2019-09-01 18:08发布

使用MVVM模式做了几个项目之后,我还在与视图模型的作用挣扎:

我所做的过去:使用模型只是作为一个数据容器中。 把逻辑来操纵视图模型数据。 (多数民众赞成在业务逻辑吧?)缺点:逻辑是不能重复使用。

我想要现在:保持视图模型尽可能薄。 将所有逻辑到模型层。 仅保留表示逻辑在视图模型。 缺点:如果数据模型层内改变使UI通知真的痛苦。

所以,我会给你一个例子,以使其更清晰的:

场景:工具来重命名文件。 类:File:表示每一个文件; 规则:包含逻辑如何重命名文件;

如果进出口下面的方法1:创建一个视图模型文件,规则和视图 - > RenamerViewModel。 把在RenamerViewModel所有逻辑:含FileViewModel和RuleViewModel的清单和程序逻辑。 方便快捷,但不能重复使用。

如果进出口下面的方法2:创建一个新的模型类 - >更名,它包含文件的列表,规则UND的程序逻辑每个文件interate过来,应用每一个规则。 对于文件,规则和更名创建一个视图模型。 现在RenamerViewModel只包含更名型号,加上两个ObservableCollections的实例来包裹更名的文件UND规则列表。 但整个逻辑是在更名模型。 因此,如果更名模型被触发操纵某些数据通过方法调用,视图模型完全不知道哪个数据进行操作。 因为模型犯规包含任何的PropertyChange通知,我会避免。 因此,商业和表示逻辑分隔,但是这使得它很难通知UI。

Answer 1:

把业务逻辑视图模型里面是一个非常糟糕的方式来做事,所以我要去快说从来没有做到这一点 ,并移动到讨论第二个选项。

把逻辑模型内部更加合理,这是一个很好的出发途径。 哪些缺点? 你的问题说:

因此,如果更名模型被触发操纵某些数据通过方法调用,视图模型完全不知道哪个数据进行操作。 因为模型犯规包含任何的PropertyChange通知,我会避免。

好了,让你的模型实现INotifyPropertyChanged肯定让你移动到更好的东西。 然而,这是真的,有时候这是不可能做到这一点 - 例如模型可以是局部类,其属性是自动生成的一个工具,并不会提高更改通知。 这是不幸的,但不是世界的末日。

如果你想买东西,然后有人为它付出; 如果它不是,让这样的通知,那么你只剩下两种选择模式:

  1. 该视图模型知道的模型,其操作(可能)引起的变化,它每个这样的操作之后更新其状态。
  2. 其他人知道哪些操作引起的变化,他们通知视图模型是改变包装后的模型来更新其状态。

第一个选项又是一个坏主意,因为实际上该回去把“商业逻辑”的视图模型内。 没有那么糟糕,因为将在视图模型所有的业务逻辑,但仍。

第二个选项是更有前途(不幸的是更多的工作):

  • 把你的业务逻辑的一部分在一个单独的类(“服务”)。 该服务将实现你会想用适当的模型实例工作进行全业务运营。
  • 这意味着,服务知道当模特属性可能会改变(这是确定:模型+服务==业务逻辑)。
  • 这项服务将提供有关改变模式给所有有关方面的通知; 您的ViewModels将采取对服务的依赖,并收到这些通知(所以他们会知道什么时候“自己”的模式已更新)。
  • 由于业务操作也由服务实现的,这仍然是很自然的(例如,当一个命令给反应是呼吁服务的适当方法的视图模型调用;请记住,视图模型本身并不了解业务逻辑)。

对于在这样一个实现的详细信息见我的答案在这里和这里 。



Answer 2:

这两种方法都是有效的,但有一个第三种方法:采用这一模式与VM层之间的服务。 如果你想保持你的模型哑巴,一个服务可以提供一个UI无关的中间人,可以强制执行可重复使用的方式您的业务规则。

因为模型犯规包含任何的PropertyChange通知,我会避免

你为什么要避免这一点? 不要误会我的意思,我倾向于保持我的模型一样傻乎乎的可能,但在你的模型实施变更通知,有时可能是有用的,而你只需要一个依赖System.ComponentModel当你这样做。 它是完全不可知的UI。



Answer 3:

我做了以下

  1. 视图仅XAML视图逻辑

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

  3. 模型,该模型验证方面的模型数据我的数据容器和业务逻辑。

  4. 其中填充数据模型服务。 例如调用Web服务器上,从磁盘加载它,保存到硬盘等。根据示例往往我的两个模式和服务将实行IPropertyChanged。 或者,他们可能有事件处理程序来代替。

任何复杂的应用程序需要伊莫另一层。 我把它叫做模型+服务,视图,视图模型。 服务抽象你的业务逻辑,并采用模型实例作为依赖或创建模型。



Answer 4:

您也可以实现IDataErrorInfo的两个:模型和视图模型,但这样做只是在模型验证,这将缓解你的方式只有在示范实施业务规则...

例如:

视图模型:

...

private Person person;

...

string IDataErrorInfo.this[string propertyName]
{
    get
    {
        string error = (person as IDataErrorInfo)[propertyName];
        return error;
    }
}

模型:

public class Person:INotifyPropertyChanged,IDataErrorInfo
{

...

   string IDataErrorInfo.this[string propertyName]
   {
        get { return this.GetValidationError(propertyName); }
   }

...

   string GetValidationError(string propertyName)
   {
        if(propertyName == "PersonName")
             //do the validation here returning the string error
   }
}

另外看看在MVCVM模式,即时通讯真正使用它,它是相当优良抽象出业务逻辑控制器类,而不是模型或视图模型



文章来源: MVVM: ViewModel and Business Logic Connection