2013-02-14 76 views
7

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

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

正如你所看到的,我没有为我的模型类中的任何INotifyPropertyChnaged支持。 我也有ViewModel的CustomerDetails屏幕,支持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被更新。 我的问题是 - 因为只有名字属性被通过视图更新,模型本身并不支持INotifyPropertyChanged的,因此项目制定者没有被调用,并且IsDirty保持等于假(因此不更新IsDirty通知在UI上)。

我知道我可以支持INotifyPropertyChanged的模型,然后注册在视图模型的Item.PropertyChanged事件,实际上是IsDirty设置为true,但是 - 由于我还使用CodeFirst,和我的模型类在我的ServerSide和我的客户端之间共享(不使用添加服务引用),我不想将INotifyPreoprtyChanged的东西添加到我的服务器端。

我considaring创建新项目,将使用T4模板复制一个个都是我的实体(如客户),并加入每一个模型INotifyPropertyChanged的支持。 这是否合理或不合理?任何其他建议?

谢谢!

回答

4

Option1。
在客户端和服务器(DTO)之间从客户端模型的实体中传输的独立实体。在模型中实施INPC。使用这些实体之间的映射。

选项2。
绑定视图仅查看模型属性。制作包装相应模型属性的视图模型属性。

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

0

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

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

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

.... 
1

那么你的方法不是最好的。更好的办法是使用像这样的虚拟机


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的精神。

+2

我明白你在说什么,但是,这将需要大量的编码(几乎)没有理由的。我应该在我的视图模型中复制我的模型的每个属性吗? – Asaf 2013-02-14 08:00:53

+0

@Asaf你是对的。我不知道你的项目。如果它只是一个小的话,这可能是一个巨大的开销。但是在大型项目中,当您有像可测试性这样的附加要求时,解耦a.s.o.这将是实现它们的一种方式。 – DHN 2013-02-14 08:07:56

1

如果您希望在模型属性改变你的UI注意到,你的模型类MUST实施INotifyPropertyChanged和类似MVVM接口(IDataErrorInfo,等...),以Notify到UI的property changed

这是因为您并不总是从视图模型更新模型,您必须在其中执行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,创建backing fieldsproperties,并为每个属性setter,该set操作后,提高OnPropertyChanged与调用的方法名称为property

0

如果你不喜欢混乱与INotifyPropertyChanged的代码,你可以尝试使用NuGet包称为PropertyChanged.Fody

模型

你可以用它像这样;

using PropertyChanged; 

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

在这个类的任何公共财产将支持INotifyPropertyChanged的