代码之家  ›  专栏  ›  技术社区  ›  Anders Rune Jensen

重构PropertyChangedEventHandler

  •  4
  • Anders Rune Jensen  · 技术社区  · 15 年前

    在我的UI代码中,我有许多具有相同基本框架的类:

    • 从InotifyPropertiesChanged派生
    • 包含以下代码:

      void NotifyPropertyChanged(String info)
      {
          if (PropertyChanged != null)
          {
              PropertyChanged(this, new PropertyChangedEventArgs(info));
          }
      }
      
      public event PropertyChangedEventHandler PropertyChanged;
      

    这似乎是一个很好的机会,可以将其融入到类中,并从中派生,而不是从inotifypropertieschanged中派生,但遗憾的是,C不支持多重继承,因此它不会真正起作用。关于如何重构这种代码有什么想法吗?

    5 回复  |  直到 13 年前
        1
  •  1
  •   Rob Fonseca-Ensor    15 年前

    你不能把这段代码放到你的超类中去吗?

    • 对象
      • 具体的notifypropertychanged类<--在此处插入
        • 从继承的任何视图模型(并停止使用多重继承)
          • 具体的视图模型
          • 另一个具体的视图模型

    大多数MVVM框架都为您提供了这样的类。

    不幸的是,由于事件周围的访问规则,您无法在没有反射的情况下将其分解为扩展方法。

        2
  •  1
  •   Sergey Teplyakov    15 年前

    也许你可以用这样的方法:

    class A1 : INotifyPropertyChanged
    {
        private string _myProperty;
        private static Expression<Func<A1, string>> myProperty = _ => _.MyProperty;
    
        public string MyProperty
        {
            get { return _myProperty; }
            set
            {
                _myProperty = value;
                InvokePropertyChanged(myProperty);
            }
        }
    
        public event PropertyChangedEventHandler PropertyChanged;
    
        private void InvokePropertyChanged<T>(Expression<Func<A1, T>> property)
        {
            PropertyChangedEventHandler Handler = PropertyChanged;
            if (Handler != null)
            {
                MemberExpression expression = (MemberExpression)property.Body;
                Handler(this, new PropertyChangedEventArgs(expression.Member.Name));
            }
        }
    }
    

    这大大减少了将来的代码更改;)

    或者你可以使用 Postsharp plug-in that automatically implements INotifyPropertyChanged .

        3
  •  1
  •   Natxo    15 年前

    一个常见的实践是让一个基类实现inotifyPropertyChanged,如下所示:

    public abstract class ViewModelBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;
    
            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
    

    然后您的类将从此类派生,并且当您希望通知属性值的更改时,可以调用OnPropertyChanged:

    public class PersonViewModel : ViewModelBase
    {
    
        public PersonViewModel(Person person)
        {
            this.person = person;
        }
    
        public string Name
        {
            get
            {
                return this.person.Name;
            }
            set
            {
                this.person.Name = value;
                OnPropertyChanged("Name");
            }
        }
    }
    
        4
  •  0
  •   adrianm    15 年前

    这是4行永远不会改变的代码。创建一个代码段!

        5
  •  0
  •   malgca    13 年前

    这可能是一个小帮助,但您可以使用params关键字,以便一次更改多个属性。

        public event PropertyChangedEventHandler PropertyChanged;
    
        public void NotifyPropertiesChanged(params string[] Properties)
        {
            if (PropertyChanged != null)
                foreach (string property in Properties)
                    PropertyChanged(this, new PropertyChangedEventArgs(property));
        }
    

    这将减少在将来通知属性更改时使用的行数。所以你使用:

    notifypropertieschanged(“foo”,“bar”);

    而不是:

    notifypropertychanged(“foo”); notifypropertychanged(“bar”);

    否则,我同意安德斯的建议,把它移到继承树上去可能是最好的。