5

I have the INotifyPropertyChanged implemented using CallerMemberName

public event PropertyChangedEventHandler PropertyChanged;

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

So this could be called in the setter of any property as - OnPropertyChanged() which would notify property changed event whenever it is being set. This is not the case for a property a getter only. For example,

private DateTime _dob;
public DateTime DateOfBirth
{
    get
    {
        return _dob;
    }
    private set
    {
        _dob = value;
        OnPropertyChanged();
        OnPropertyChanged("Age");
    }
}

public int Age
{
    get
    {
        return DateTime.Today.Year - _dob.Year;
    }
}

OnPropertyChanged() works fine for DateOfBirth, but to notify Age changed, I should remember to call OnPropertyChanged("Age") within the setter of DateOfBirth. I feel this makes the code difficult to maintain over time. If a new property depends on Age, that also needs to be Notified in the setter of DateOfBirth. Is there a better way to do this without calling OnPropertyChanged("Age")?

Toan Nguyen
  • 11,263
  • 5
  • 43
  • 59
Carbine
  • 7,849
  • 4
  • 30
  • 54
  • Does this `OnPropertyChanged()` only works on setter? If not, you could try put the `return` statement in a try-finally, and call the `OnPropertyChanged()` there. – Guilherme Oliveira Feb 14 '14 at 10:25
  • Could you please elaborate. OnPropertyChanged works always, but it should be notified only when someone changes the value. So it makes sense to have it in setter. I don't understand where and why i will need a try-finally? – Carbine Feb 14 '14 at 10:33
  • If you don't want to call `OnPropertyChanged("Age")`, with "Age" as a parameter when you set the DOB's value, on the `Age's get` you could return the value inside a `try`, and inside the `finally`, you could call the `OnPropertyChanged()`, without the parameter. – Guilherme Oliveira Feb 14 '14 at 10:43
  • This will not work. The reason I am using OnPropertyChanged is, if someone changes DOB, OnPropertyChanged will trigger UI to access Get of Age. If I move OnpropertyChanged within Get of Age, it will go into an infinite loop of again and again trying to access get and getting a changed notification. – Carbine Feb 14 '14 at 11:10
  • Guilherme's comments make no sense at all. Property notification obviously needs to be done when setting, not getting, and try/finally achieves nothing (other than fire the event even when there's an exception in the getter, which is just bizarre). – Jim Balter May 18 '14 at 02:14

2 Answers2

6

As long as your dependent property is in the same class you can use Poma's approach but if the dependent properties are in different classes its getting harder with that approach.

In my opinion the conceptually right thing to do would be to add a PropertyChanged listener.

In this case that would be something like

In the constructor:

this.PropertyChanged += new PropertyChangedEventHandler(SubPropertyChanged);

And outside:

private void SubPropertyChanged(object sender, PropertyChangedEventArgs e)
{
    if (e.PropertyName == "DateOfBirth")
    {
       OnPropertyChanged("Age");
    }
}

This then also works if you have a dependent property somewhere completely different and also if you cannot change your source class anymore.

blacktemplar
  • 699
  • 1
  • 7
  • 21
-4

One way to do that is to define your attribute and do some reflection in OnPropertyChanged to notify all dependent properties. You may want to cache attributes to use reflection only in class initializer because reflection is pretty slow.

private DateTime _dob;
public DateTime DateOfBirth
{
    get
    {
        return _dob;
    }
    private set
    {
        _dob = value;
        OnPropertyChanged();
    }
}

[DependsOnProperty("DateOfBirth")]
public int Age
{
    get
    {
        return DateTime.Today.Year - _dob.Year;
    }
}
Poma
  • 8,174
  • 18
  • 82
  • 144
  • That DependsOnProperty is from a Framework isn't it? – El Mac Aug 27 '14 at 07:06
  • @ElMac couldn't find it in google. But there are namespaces to avoid conflicts anyway. – Poma Aug 29 '14 at 11:46
  • 1
    What is the attribute DependsOnProperty? Is something the OP has to implement and you are just giving an example? – Dzyann May 04 '15 at 14:59
  • This is the correct answer and better way of implementing it. Marking with dependesOnProperty attribute will trigger the notification to UI. I really don't know why people down voted this. – Vimal CK May 03 '22 at 12:20