How to rise PropertyChanged event without passing property name as a string?

In wpf we often use following pattern for bindable properties:

private Foo _bar = new Foo();
public Foo Bar
{
    get { return _bar; }
    set
    {
        _bar = value;
        OnPropertyChanged();
    }
}

public void OnPropertyChanged([CallerMemberName] string property = "")
{
    if (PropertyChanged != null)
        PropertyChanged(this, new PropertyChangedEventArgs(property));
}

CallerMemberNameAttribute does nice magic, generating for us "Bar" parameter from setter name.

However, often there are properties without setter or dependent properties:

private Foo _bar;
public Foo Bar
{
    get { return _bar; }
    set
    {
        _bar = value;
        OnPropertyChanged();
    }
}

public bool IsBarNull
{
    get { return _bar == null; }
}

In given example, when Bar is changed then IsBarNull needs event too. We can add OnPropertyChanged("IsBarNull"); into Bar setters, but ... using string for properties is:

  • ugly;
  • hard to refactor (VS's "Rename" will not rename property name in string);
  • can be a source of all kind of mistakes.

WPF exists for so long. Is there no magical solution yet (similar to CallerMemberNameAttribute)?

Jon Skeet
people
quotationmark

Use C# 6 and the nameof feature:

OnPropertyChange(nameof(IsBarNull));

That generates equivalent code to:

OnPropertyChange("IsBarNull");

... but without the fragility.

If you're stuck on earlier versions of C#, you can use expression trees for this, but I regard that as a bit of a hack and a potential performance issue (as the tree is recreated on each call). nameof doesn't require any library support, just a new compiler - so if you upgrade to VS 2015 (or later, dear readers from the future...) you should be fine.

people

See more on this question at Stackoverflow