简体   繁体   中英

When do I need to implement INotifyPropertyChanged?

I have seen apps implementing this interface everywhere. In many cases, we could use the new property syntax like

public int Foo { get; set; }

which I like very much. However, in order to implement this interface, this one has to turn into 10 lines or so. This makes the code very cluttered, and I'm not sure if it also hurts performance.

Can someone explain when this interface is really necessary?

You implement that interface when your data object needs to advertise (notify) that a property has changed. This is especially important when using databinding, and very useful when using the Observer pattern.

Check here for an approach i follow when i have lots of properties that need to notify of changes.

It's necessary if you want to subscribe to notifications that a property has changed. If you don't need to (and no 3rd party libraries need to) you don't have to implement this interface.

Do it like that

public class ViewModelBase : INotifyPropertyChanged

{

protected void SetProperty<t>(ref T newValue, ref T currentValue, bool notify, string propertyName, params string[] additionalProperties)
{
    bool changed = notify && ((newValue != null && !newValue.Equals(currentValue)) || (newValue == null && currentValue != null));
    currentValue = newValue;
    if (changed)
    {
        OnPropertyChanged(propertyName);

        if (additionalProperties != null)
            foreach (string additionalProperty in additionalProperties)
                OnPropertyChanged(additionalProperty);
    }
}

protected virtual void OnPropertyChanged(string propertyName)
{
    if (this.PropertyChanged != null)
        this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}

public event PropertyChangedEventHandler PropertyChanged;

}

public class MyRealViewModel : ViewModelBase

{ public int NumberOfItems { get { return _numItems; } set { SetProperty(ref value, ref _numItems, true, "NumberOfItems"); } }

public bool SomeKindOfFlag
{
    get { return _flag; }
    set { SetProperty(ref value, ref _flag, false, ""); }
}

public LightSabre WeaponOfChoice
{
    get { return _weapon; }
    set { SetProperty(ref value, ref _weapon, true, "WeaponOfChoice", "SomeKindOfFlag", "NumberOfItems"); }
}

private bool _flag;
private int _numItems;
private LightSabre _weapon;

}

public class LightSabre

{

public string LightSabreName { get; set; }

public override bool Equals(object obj)
{
    if (obj != null && obj as LightSabre != null)
        return ((LightSabre)obj).LightSabreName == this.LightSabreName;

    return false;
}

}

It's extracted out of an answer above, really helped me.

This interface is necessary when working with libraries or other features within the framework that expect it.

The most common is when using a UI framework like WPF with its data binding. In order for the UI to "know" that your property has changed, so it can reflect the contents of a TextBox, for example, the object to which its bound needs to either be a DependencyObject and the property needs to be a DependencyProperty, or you need to implement INotifyPropertyChanged.

This is what makes 2-way databinding work properly.

That being said, it's common to implement this on a base class, which can make your subclass implementation only be a few lines per property. (You can't use automatic properties, but you potentially only need a couple of extra lines in the setter if you use a base class.)

An alterative is to use Microsoft's ReactiveExtensions (Rx) framework to wrap all up all the plumbing work into a single Observable<T> object.

See this StackOverflow question and answers for an example of how to do this.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM