重构PropertyChangedEventHandler

时间:2010-02-02 11:43:46

标签: c# .net wpf

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

  • 派生自INotifyPropertyChanged
  • 包含以下代码:

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

这似乎是一个很好的机会,可以考虑到一个类并从中派生而不是INotifyPropertyChanged,但遗憾的是C#不支持多重继承,所以它不会真正起作用。关于如何重构这种代码的任何想法?

5 个答案:

答案 0 :(得分:1)

也许你可以使用这样的东西:

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

答案 1 :(得分:1)

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

  • 对象
    • 您的具体NotifyPropertyChanged类&lt; - 在此插入
      • 您的viewmodel继承的是什么(并阻止您使用多重继承
        • 您的具体视图模型
        • 另一个具体的viewmodel

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

由于事件的访问规则,不幸的是,你无法将其分解为没有反射的扩展方法。

答案 2 :(得分:1)

通常的做法是让一个实现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");
        }
    }
}

答案 3 :(得分:0)

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

答案 4 :(得分:0)

这可能是一个很小的帮助,但你可以使用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( “条”);

否则,我同意安德斯关于将其移植到继承树上的建议可能是最好的。