在MVVM模式中在模型和视图模型之间进行绑定的正确方法是什么?

时间:2016-03-03 08:22:19

标签: c# wpf mvvm

我用了几天时间来改进我的MVVM应用程序,但是我发现我实际上并不知道什么是正确的方法。

在mvvm中进行绑定的正确方法是什么?

选项一:

<img src="data:image/png;base64,YOUR_BASE64_HERE"/>

选项二

public class CustomerViewModel : ViewModelBase
{

     public CustomerViewModel(Customer c)
     {
      _customer = c;
     }

     private readonly Customer _customer;

     public string CustomerName
     {
       get { return _customer.Name; }
       set
          { 
           _customer.Name = value;
           RaisePropertChanged("CustomerName");
          }
     }        
}

3 个答案:

答案 0 :(得分:1)

假设这两种解决方案都适合你 -

如果您只有一个属性(CustomerName)要绑定到您的视图,那么选项1.正如@Default正确指出的,如果您使用选项2,则无法在将值更新回Customer c对象时您更改CustomerName属性的值。

如果您需要绑定Customer的所有属性。直接绑定Customer对象并确保Customer类实现INotifyPropertyChanged接口。

所以它会像这样 -

public class CustomerViewModel : ViewModelBase{

    public CustomerViewModel(Customer c){
_customer = c;
}

private readonly Customer _customer;

public Customer Customer{
 get{return _customer;}
 set{_customer.Name = value;
   RaisePropertChanged("Customer");
 }
 }
}
public Customer:INotifyPropertyChanged
{
    #INotifyPropetyChanged implementation
    private string _customerName;

    public string CustomerName{
     get{return _customerName;}
     set{_customerName = value;
       RaisePropertChanged("CustomerName");
     }
}

然后用CustomerViewModel.Customer.Name

绑定它

修改 在旁注 - 再次@Default正确指出...确保将数据的持久性从模型分离回数据库以便正确处理。即,只有在单击“保存”按钮等时才将其保存到数据库中。否则,每次更改属性都会调用太多。还有多个用户更新相同视图模型的问题。你只需记住这些要点而不是违反它们。

答案 1 :(得分:1)

这是一个有趣的问题,如何处理WPF应用程序中的普通对象。一方面,您通常不想将INPC和其他UI相关内容添加到业务对象中,因为它们可能在应用程序的其他部分中使用,与WPF无关。另一方面,创建与普通对象有许多共同点的单独ViewModel是一个很大的开销。最近我在Pluralsight上看到了关于这个话题的精彩课程: https://app.pluralsight.com/library/courses/wpf-mvvm-advanced-model-treatment/description

作者坚持使用选项一方法,当POCO对象被视图模型包装时,它们依次实现INPC和IDataErrorInfo接口,跟踪更改等。 作者建议使用T4模板为每个POCO对象创建VM包装器。借助反射的T4模板中的逻辑从平面对象中提取属性并在相应的VM中生成包装器属性。有趣的方法,值得尝试。

答案 2 :(得分:0)

一般情况下,我使用MVVM中的Option 2和automapper将模型映射到视图模型,反之亦然。我认为这完全取决于你想用VM做什么以及差异有多大。

我在VM类上工作的项目包含更多字段和逻辑,直接使用VM的属性而不是像在选项1中那样对象属性的属性更加舒适:CustomerViewModel.Customer.Name