将INotifyPropertyChanged添加到模型?

我在我的wpf MVVM(基于Prism的)应用程序中遇到了一些设计问题,很乐意得到你的建议。 我的模型非常简单:

public class Customer { public string FirstName {get;set;} public string LastName {get;set;} } 

如您所见,我的Model类没有任何INotifyPropertyChnaged支持。 我还在CustomerDetails屏幕上有ViewModel,它支持INotifyPropertyChanged。

 public class CustomerDetailsViewModel:INotifyPropertyChanged /*Or NotificationObject*/ { /*INotifyPropertyChanged event */ private Customer item; public Customer Item { get{return item;} set { item=value; //Raise PropertyChanged //Set IsDirty to true } } } 

在我看来,我正在使用绑定到Item.FirstName和我正在更新的ViewModel。 我的问题是 – 因为只有FirstName属性通过View更新,而Model本身不支持INotifyPropertyChanged,因此Item setter没有被调用,并且IsDirty仍然等于false(因此不会更新IsDirty通知)用户界面)。

我知道我可以在模型中支持INotifyPropertyChanged,然后在视图模型中注册到Item.PropertyChanged事件,并实际将IsDirty设置为true,但是 – 因为我也使用CodeFirst,我的Model类在我的ServerSide之间共享和我的客户端(不使用添加服务参考),我不想将INotifyPreoprtyChanged内容添加到我的服务器端。

我正在考虑创建新项目,它将使用T4模板逐个复制我的所有实体(作为客户)并为每个模型添加INotifyPropertyChanged支持。 那是否合理与否? 还有其他建议吗?

谢谢!

选项1。
在客户端和服务器(DTO)之间传输的独立实体,来自实体,这些实体是客户端的模型。 在模型中实现INPC 。 使用这些实体之间的映射。

选项2。
绑定视图仅查看模型属性。 创建视图模型属性,其中包含相应的模型属性。

选项3。
是前两个选项的混合。 不要在视图模型中聚合模型。 使用模型和视图模型之间的映射。 创建与模型属性对应的视图模型属性。

那么你的方法根本不是最好的。 更好的方法是使用这样的VM

 public class CustomerDetailsViewModel : INotifyPropertyChanged { public CustomerDetailsViewModel(Customer customer) { _item = customer; } private Customer _item; public string FirstName { get { return _item != null ? _item.FirstName : null; } set { if (_item == null) _item = new Customer(); // just an example, probably it's not the desired behavior _item.FirstName = value; RaisePropertyChanged(...); } } ... } 

这将坚持MVVM的精神。

如果您希望UI在模型属性发生更改时注意到 ,您的模型类必须实现INotifyPropertyChanged和类似的MVVM接口( IDataErrorInfo等…),以便向UI Notify property changed

这是因为您并不总是从viewmodel更新模型,您必须在其中实现INotifyProperyChanged并通知更改。

当您无法在模型类中实现INotifyPropertyChanged时,在视图模型中包含相应的模型属性,这使得视图模型非常快速地增长并创建不必要的代码重复。

场景例如:

 public class Customer { public string FirstName {get;set;} public string LastName {get;set;} // Changes the first name. public void ChangeFirstName(string newName) { FirstName = newName; //The UI will never know that the property changed, and it won't update. } } 

解:

在模型类中实现INotifyPropertyChanged ,为properties创建backing fields ,对于每个属性setter ,在set操作之后,使用property名称引发OnPropertyChanged调用方法。

我认为你走在正确的轨道上。 在服务器端,您不需要INotifyPropertyChanged ,因此不要将其添加到服务器端的域类中。

您可以在客户端项目中添加一些构建符号,例如“WPF”; 并且在代码中,只有存在“WPF”构建符号时,第一个定义才实现INotifyPropertyChanged 。 然后只需添加服务器端域类作为演示应用程序的链接。 就像是;

 #if WPF public class MyEntity : INotifyPropertyChanged #else public class MyEntity .... 

如果您不喜欢使用INotifyPropertyChanged代码使模型混乱,可以尝试使用名为PropertyChanged.Fody的NUGet包。

你可以像这样使用它;

 using PropertyChanged; [ImplementPropertyChanged] public class Customer { public string FirstName {get;set;} public string LastName {get;set;} } 

此类中的任何公共属性现在都支持INotifyPropertyChanged