开发者

Refactoring PropertyChangedEventHandler

In my UI code I have a lot classes with the same basic skeleton:

  • derives from INotifyPropertyChanged
  • contains the following code:

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

It seems like a perfect chance to factor into a class and 开发者_开发问答to derive from that instead of INotifyPropertyChanged, but sadly C# doesn't support multiple inheritance so it's not really going to work. Any ideas on how to refactor this kind of code?


Can't you just put this code into your superclass's superclass?

  • Object
    • Your concrete NotifyPropertyChanged class <-- Insert here
      • Whatever your viewmodel inherited from (and stopped you using multiple inheritance
        • Your concrete viewmodel
        • Another concrete viewmodel

Most MVVM Frameworks provide such a class for you.

Because of the access rules around events, you can't factor this out into an extension method without reflection, unfortunately.


Maybe you can use something like this:

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));
        }
    }
}

This significally reduce future code changes;)

Or you can use Postsharp plug-in that automatically implements INotifyPropertyChanged.


A common practice is to have a base class implementing INotifyPropertyChanged, like this:

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));
        }
    }
}

Then your classes will derive from this one, and you can call OnPropertyChanged when you wish to notify changes on the value of a property :

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");
        }
    }
}


It is 4 lines of code that will never change. Create a snippet!


This is probably a small help but you could use the params keyword so that you could change more than one property at a time.

    public event PropertyChangedEventHandler PropertyChanged;

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

This decreases the amount of lines you use when notifying property changes in the future. So you use:

NotifyPropertiesChanged("foo", "bar");

Instead of:

NotifyPropertyChanged("foo"); NotifyPropertyChanged("bar");

Otherwise, I agree with Anders' suggestion of moving it up the inheritance tree would probably be best.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜