MVVM 中的 ViewModel 是什么

What is in ViewModel in MVVM

我花了很长时间在 WPF 中搜索 MVVM。我明白为什么要使用它。这对我来说很清楚。 我不知道的是 ViewModel 本身的内容。我知道这是视图和模型之间的连接。另外,我知道(至少,大多数程序员的建议)实现了 INotifyPropertyChanged。添加到此,命令。

假设我有这个模型(使用 EF 6 的代码优先):

public class City
{
    [Key, DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int CityId { get; set; }

    [DataType("VarChar"), MaxLength(25), Required]
    public string CityName { get; set; }
}

我的问题是:

1- 在我见过的许多示例中,它们在 VM 中再次重新创建相同的字段。目的是什么,是否足以拥有整个对象(在我的示例中为城市)。如果有很多字段呢!.

2- 为了能够在我的视图 (CRUD) 中使用它,我的示例中的 CityVm() 会怎么样?

感谢任何帮助。

1- In many examples I've seen, they recreate the same fields again in VM. What is the purpose, is it enough to have the whole object (City in my example). How about if there are many fields!.

由于 视图模型 负责实现视图的逻辑并针对模型执行操作,因此在某些情况下某些属性不一定是视图的一部分模型,但它们只是为了满足视图的要求。

例如,假设您的模型有 NameSurname,并且您想在视图中显示这两个属性的串联。您可以使用绑定表达式或在 视图模型 :

中实现 属性 来实现这一点
public string FullName => $"{Model.Name} {Model.Surname}"; 

2- To be able, to use it in my View (CRUD), how is the CityVm() will be in my example?.

这个问题没有具体答案。但是你至少需要 Model 属性 来存储给定的 City.

MVVM 模式中的视图模型封装了视图的表示逻辑和数据。它没有对视图的直接引用或关于视图的特定实现或类型的任何知识。视图模型实现视图可以数据绑定的属性和命令,并通过更改通知事件通知视图任何状态更改。视图模型提供的属性和命令定义了 UI 提供的功能,但视图决定了如何呈现该功能。

视图模型负责协调视图与所需的任何模型 classes 的交互。通常,视图模型和模型 classes 之间存在一对多关系。视图模型可以选择将模型 classes 直接暴露给视图,以便视图中的控件可以直接将数据绑定到它们。在这种情况下,模型 classes 将需要设计为支持数据绑定和相关的更改通知事件。

视图模型可以转换或操作模型数据,以便视图可以轻松使用它。视图模型可以定义额外的属性来专门支持视图;这些属性通常不会成为(或不能添加到)模型的一部分。例如,视图模型可以组合两个字段的值以使视图更容易呈现,或者它可以计算最大长度的字段的剩余输入字符数。视图模型还可以实现数据验证逻辑以确保数据一致性。

视图模型还可以定义视图可用于在 UI 中提供视觉变化的逻辑状态。视图可以定义反映视图模型状态的布局或样式更改。例如,视图模型可以定义一个状态,指示数据正在异步提交到 Web 服务。视图可以在此状态期间显示动画以向用户提供视觉反馈。

通常,视图模型将定义可以在 UI 中表示并且用户可以调用的命令或操作。一个常见的例子是视图模型提供了一个提交命令,允许用户将数据提交到 Web 服务或数据存储库。视图可以选择用按钮来表示该命令,以便用户可以单击该按钮来提交数据。通常,当命令不可用时,其关联的 UI 表示将被禁用。命令提供了一种封装用户操作并将它们与 UI.

中的视觉表示完全分开的方法

总而言之,视图模型具有以下主要特征:

  • 视图模型是非可视的 class,并且不派生自任何 WPF 基础 class。它封装了支持应用程序中的用例或用户任务所需的表示逻辑。视图模型可独立于视图和模型进行测试。
  • 视图模型通常不直接引用视图。它实现视图可以数据绑定到的属性和命令。它通过 INotifyPropertyChangedINotifyCollectionChanged 接口通过更改通知事件通知视图任何状态更改。
  • 视图模型协调视图与模型的交互。它可以转换或操作数据,以便它可以很容易地被视图使用,并且可以实现模型上可能不存在的其他属性。它还可以通过 IDataErrorInfoINotifyDataErrorInfo 接口实现数据验证。
  • 视图模型可以定义视图可以直观地向用户表示的逻辑状态。

这是一个非常广泛的话题,主要基于很多观点。 MVVM 模型不是一成不变的,有很多不同的实现方式。

在我看来,ViewModel 有两个主要目的:

1) 将模型暴露给视图。 有两种方法可以做到这一点。让您的模型包装您的 CRUD 对象并管理 NotifyPropertyChange。在这种情况下,您的 ViewModel 通常只将模型暴露给视图而不用它做太多其他事情,视图直接绑定到模型,或者通过简单的传递属性。

另一种常见情况是将您的模型作为 CRUD。在这种情况下,ViewModel 管理 NotifyPropertyChange 通知并管理模型更新等。

2) 管理表示逻辑和数据。 您需要绑定和存储许多在模型中没有位置的东西。模型就是数据。它很可能是从数据库加载的。然而,视图需要跟踪其他属性。举个例子:假设你的城市对象显示在一个列表中,你想用一个按钮来显示或隐藏它。隐藏它的逻辑,以及它被隐藏的布尔值不属于视图,与模型中的基础数据无关,所以它位于视图模型中。

同样,也许你有一个CityPopulation属性。在您的视图中,您想用红色突出显示人口超过 1,000,000 的城市。您的视图模型具有 属性:

bool LargeCity
{
    return CityPopulation<1000000;
}

并且您使用样式触发器呈现标签。

另一个示例,包含要绑定的画笔 属性 的 ViewModel,我认为这可能是一种常见的 但不好的做法 。 slugster 还在下面评论说视觉元素不应出现在 ViewModel 中。

Brush HighlightBrush
{
    get
    {
        if (CityPopulation<1000000)
        {
            return Brushes.Red;
        }
        else
        {
            return Brushes.Black;
        }
}