13

我目前正在研究我第一次真正尝试使用 MVVM,并且一直在阅读有关如何最好地实现它的各种文章。

我目前的想法是有效地使用我的数据模型作为数据传输对象,使它们可序列化并让它们同时存在于客户端和服务器端。这似乎是一个合乎逻辑的步骤,因为这两种对象类型实际上只是属性 getter 和 setter 的集合,而中间的另一层似乎完全是矫枉过正。

显然,INotifyPropertyChanged 会在服务器端无法正常工作,因为没有要与之通信的 ViewModel,但只要我们小心地从服务层中的数据模型构造我们正确的域模型对象,而不是处理服务器端的数据模型我不认为这应该是一个大问题。

我在阅读中没有找到太多关于这种方法的信息,所以我想知道这是否是一个非常标准的事情,这是否只是假设是在多层环境中执行 MVVM 的事实上的方式?如果我对事物有完全错误的想法,那么对其他方法的想法也会受到赞赏。

4

3 回答 3

6

你可以使用任何你觉得舒服的模型,是的,你的所有属性都需要 INotifyPropertyChanged 行为。这将如何影响服务层完全取决于您的实现。

我假设您认为您认为绑定到您的 DTO?

我的看法是应用程序的各层之间存在阻抗不匹配,即您的域模型可能看起来与您的关系模型相似,但存在细微但至关重要的差异。域模型和您的 DTO 之间也存在不匹配(对象可能是扁平化的、计算的属性等……)。直接绑定到 DTO 很诱人,因为它们可能被设计为具有特定操作所需的内容,但是 DTO 与视图为实现预期结果所需的内容之间也存在阻抗不匹配。这就是视图模型的用武之地。视图模型负责将 DTO 属性代理到视图,它负责让视图知道是否存在验证错误,并将命令路由到适当的处理程序(保存、删除等) , ..

我倾向于通过以下方式进行设置:

// POCO object. Serializable.
public class AddressDto 
{    
   public int Id { get; set; }
   public string Street { get; set; }    
   public string City { get; set; }    
   public string Country { get; set; } 
}

// IDataErrorInfo for validation.
public class AddressViewModel : INotifyPropertyChanged, IDataErrorInfo
{
   private readonly AddressDto addressDto;

   public AddressViewModel(AddressDto addressDto)
   {
      this.addressDto = addressDto;      
   }

   public int Id { /* get and set for property changed event and update dto */ }
   public string Street { /* get and set for property changed event and update dto  */ }
   public string City { /* get and set for property changed event and update dto  */ }
   public string Country { /* get and set for property changed event and update dto  */ }
   ...

   // IDataErrorInfo implementation
}

public class EditAddressViewModel : INotifyPropertyChanged
{
   public AddressViewModel Address { /* get and set for property changed event */ }
   public ICommand Save { /* setup command */ }
   public ICommand Cancel { /* setup command */ }

   private void Save()
   {
   }

   private void Cancel()
   {
   }
}

然后您的 EditAddressView 将绑定到 EditAddressViewModel。基本上规则是你所有的 UI 行为都应该用你的视图模型来表达。

是的,这确实意味着额外的工作,但是您可以做一些事情来简化一些事情(代码生成等)。我实际上正在开发一个旨在使用流利的 api 简化整个 MVVM 过程的库。在http://fluentviewmodel.codeplex.com/上查看

于 2010-04-28T09:23:02.570 回答
3

我不是这方面的专家。我有同样的情况。我同意你的观点,这是相当过分的。我已经使用这个解决方案很长一段时间了,没有遇到任何问题。INotifyPropertyChanged 对我来说不是什么大问题,因为服务器端的任何内容都不会订阅 PropertyChanged 事件。如果您将在数据模型上使用继承,那么所有这些都必须是可序列化的。在我的场景中,我的数据模型有两个基类:一个用于数据传输,另一个不用于。

于 2010-04-27T13:32:09.300 回答
2

我决定在我的 ViewModel 上有一个属性“模型”。在模型本身中,我已经实现了 IPropertyNotifyChanged 和 IDataErrorInfo。因此,在我的 ViewModel 中,我跳过了代码将简单地“贯穿”到模型的属性。相反,视图直接绑定到这些属性的模型。

对于更复杂的情况,我必须调整模型中的数据以适应视图,我在 ViewModel 中执行此操作。此外,命令等都在 ViewModel 中。但我看不出有什么理由让 ViewModel 中的样板代码重复我在模型中已有的东西。

于 2010-04-28T09:49:58.747 回答