【问题标题】:Adding INotifyPropertyChanged to Model?将 INotifyPropertyChanged 添加到模型?
【发布时间】:2013-01-29 23:10:41
【问题描述】:

我在我的 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 更新,并且模型本身不支持 INotifyPropertyChanged,因此没有调用 Item 设置器,并且 IsDirty 仍然等于 false(因此不会更新 IsDirty 通知用户界面)。

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

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

谢谢!

【问题讨论】:

    标签: c# .net wpf mvvm inotifypropertychanged


    【解决方案1】:

    选项1。
    将在客户端和服务器 (DTO) 之间传输的实体与作为客户端模型的实体分开。在模型中实现INPC。在这些实体之间使用映射。

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

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

    【讨论】:

      【解决方案2】:

      嗯,你的方法根本不是最好的。使用这样的虚拟机会更好

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

      【讨论】:

      • 我明白你在说什么,但这将需要大量编码(几乎)没有理由。我应该在我的视图模型中复制我的模型的每个属性吗???
      • @Asaf 你是对的。我不知道你的项目。如果它只是一个小的,它可能是一个巨大的开销。但是在较大的项目中,当您有额外的要求(如可测试性)时,解耦 a.s.o.这将是实现它们的一种方法。
      【解决方案3】:

      如果您希望您的 UI 在您的模型属性发生更改时注意到,您的模型类必须实现 INotifyPropertyChanged 和类似的 MVVM 接口(@98​​7654322@ 等。 .) 以Notify 到property changed 的UI。

      这是因为您并不总是从视图模型更新模型,您必须在视图模型中实现 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 调用的方法。

      【讨论】:

        【解决方案4】:

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

        你可以这样使用它;

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

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

        【讨论】:

          【解决方案5】:

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

          您可以在您的客户端项目中添加一些构建符号,例如“WPF”;并且在代码优先定义中实现INotifyPropertyChanged 仅当存在“WPF”构建符号时。然后只需将您的服务器端域类作为链接添加到您的演示应用程序。类似的东西;

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

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-09-30
            • 2015-12-05
            • 2020-03-24
            • 2020-04-18
            • 2018-01-23
            • 2014-12-02
            相关资源
            最近更新 更多