4

我试图了解模型到 ViewModel 的关系,但我一直遇到同样的问题。假设我们有一个只有一个字段的“Person”类:

public class Person
{
   public string Name;
}

在下一阶段,我的 XAML 艺术家创建了一个用户控件来呈现一个人,他根据 MVVM 的实践需要将他的视图与 VMPerson(视图模型人)相关联,所以现在我添加另一个类:

public class VMPerson : INotifyPropertyChange
{
   private Person person;

   public VMPerson():this(new Person()){}

   public VMPerson(Person person)
   {
      this.person = person;
   }

   public Name
   { get { return person.name; }
   { set { person.name = value; PropertyChange("Name"); }
}

所以现在我几乎所有的东西都设置好了。但是我的 VM 类与我的模型类的变化有什么关系呢?如果我添加 INotifyPropertyChanged 并在模型中为“名称”添加一个属性,我最终会得到与我的 ViewModel 类非常相似的东西,这是一个我不需要的额外层。有没有办法让我的模型类保持原样,并且仍然会在视图模型类中得到通知?如果除了使用 INotifyPropertyChanged 机制或将在模型中实现的任何类似方法之外别无他法,为什么我需要 VM?只是为了将几个“模型”类聚合到一个将提供给视图的类的情况吗?

我认为我的理解中一定遗漏了一些东西,因为根据我的描述,在我看来,在使用 View 代码隐藏作为控制器时,模型到视图模式会比 MVVM 更好的抽象,但我当然不确定. 有人可以向我解释我错过了什么吗?谢谢。

4

3 回答 3

3

将 viewmodel 代码放入模型中并不是最好的主意

确实,在许多情况下,视图模型开始时看起来像是额外的代码层,并没有真正增加任何价值,但关键是它们可以进化

VM 的作用是为视图提供便利——INotifyPropertyChanged这就是一种便利,而模型的作用是封装您的业务逻辑。随着代码功能的增长,将变得越来越丰富;在某些时候,它的代码量甚至可能比您的模型大得多。所以区分是为了方便和业务逻辑部分很好地分开,这对代码的可维护性有很好的影响。

将视图模型代码放入视图不是最好的主意

这里的原因是不同的:如果您这样做,然后需要将视图模型与另一种类型的视图一起使用,您还必须将所有逻辑复制到其他视图的代码隐藏中。重复是不好的;干是好的。

考虑到 MVVM 的一个非常重要的特性是它提供了可测试性,并且可测试性必然意味着至少两种类型的视图(真实视图和模拟视图),这种方法的必要性变得显而易见。

于 2012-05-11T11:43:44.587 回答
1

视图模型的一个目的是从模型中获取数据,以必须可视化的方式处理它。

例如,在您的模型中,您可能拥有 DateOfBirth 信息,并且您想要可视化实际年龄。

在这种情况下,您应该在 ViewModel 中进行处理(将 DateOfBirth 转换为实际年龄,例如 DateTime.Now.Year - DateOfBirth.Year)。

在您的特定情况下,ViewModel 只是模型数据的包装器(不处理),显然不需要 Viewmodel。

为了在 ViewModel 中获得模型更改(对于不需要在 VM 中处理的属性),我通常也在模型中实现 INotifyPropertyChanged。这避免了 ViewModel 中的许多包装器属性。

在我的 ViewModel 中,我会有一些想法

_model.PropertyChanged += PropertyChangedEventHandler(OnPropertyChangedModel);

void OnPropertyChangedModel(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
    OnPropertyChanged(e.PropertyName);
}

请注意,在这种情况下,模型属性会直接发送到 View(在 ViewModel 中不进行处理)。

于 2012-05-11T11:59:42.797 回答
1

我看它的方式如下: - ViewModel,这在某种程度上就像旧 MVP 中的 Presenter,它将包含和加入各种业务功能(如使用 IDealService 和 IStaticDataService)。

对我来说,模型非常接近 DataModel,它只是代表数据。

如果 VM 有太多与数据相关的位,我通常将它们移动到模型中并使用 VM 中的实例。

即你可以有:

public class VMPerson : INotifyPropertyChange
{
   public Person PersonItem {get; set;}

   public VMPerson()
   {
      PersonItem = new Person();
   }
}

您仍然可以通过以下方式获取 Person 的姓名: {Binding PersonItem.Name}

我同意如果您的原始 Person 类不继承 INPC,将很难使其成为 Notifiable。

于 2012-05-11T12:36:23.870 回答