How do I raise PropertyChanged
for SomeProperty
in class B
?
This example does not compile since PropertyChanged
is not accessible this way...
public class A : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
}
public class B : A
{
private object _someProperty;
public object SomeProperty
{
get => _someProperty;
set
{
_someProperty = value;
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SomeProperty)))
}
}
}
Solution 1:
You can use this RaisePropertyChangedExtension
:
public static class RaisePropertyChangedExtension
{
public static void RaisePropertyChanged(this INotifyPropertyChanged @this, [CallerMemberName] string propertyName = null)
{
var declaringType = @this.GetType().GetEvent(nameof(INotifyPropertyChanged.PropertyChanged)).DeclaringType;
var propertyChangedFieldInfo = declaringType.GetField(nameof(INotifyPropertyChanged.PropertyChanged), BindingFlags.Instance | BindingFlags.NonPublic);
var propertyChangedEventHandler = propertyChangedFieldInfo.GetValue(@this) as PropertyChangedEventHandler;
propertyChangedEventHandler?.Invoke(@this, new PropertyChangedEventArgs(propertyName));
}
}
Like this:
public class B : A
{
private object _someProperty;
public object SomeProperty
{
get => _someProperty;
set
{
_someProperty = value;
this.RaisePropertyChanged();
}
}
}
In my opinion this is the best solution I know so far.
Disadvantage is that you're able to raise PropertyChanged
from another class like this:
public class C
{
public C(B b)
{
b.RaisePropertyChanged(nameof(b.SomeProperty));
}
}
It's not good practise to raise PropertyChanged
from other classes this way, so i'm not concerned by this disadvantage.
This solution is inspired by Thomas Levesque's answer here: Simple small INotifyPropertyChanged implementation
Solution 2:
You can create a protected RaisePropertyChanged
in the base class A
:
public class A : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
And call the method in the derived class B
:
public class B : A
{
private object _someProperty;
public object SomeProperty
{
get => _someProperty;
set
{
_someProperty = value;
RaisePropertyChanged();
}
}
}
Disadvantage is that you have to implement the RaisePropertyChanged
method for each new base class you're creating on the opposite you avoid the disadvantage that Solution 1 had.