NotifyPropertyChanged not firing in derived class

589 Views Asked by At

I have these 3 classes

[AddINotifyPropertyChangedInterface]
public abstract class BaseViewModel
{

}

public abstract class XXXViewModelBase : BaseViewModel
{
   public int SelectedAreaId { get; set; }
}

public class XXXSelectorViewModel : XXXViewModelBase
{
    //public new int SelectedAreaId { get => base.SelectedAreaId; set => base.SelectedAreaId = value; }
    public void OnSelectedAreaIdChanged()
    {
        // Does not fire
    }
}

With the code as shown, OnSelectedAreaIdChanged does not fire when SelectedAreaId is changed. If I uncomment the code, then OnSelectedAreaIdChanged does fire.

Is that expected behaviour? Is there any way around this other than the way I've done it?

2

There are 2 best solutions below

1
On BEST ANSWER

Yes it is expected behavior, because Fody doesn't support this. More Info Here

3
On

Does this give you what you want?

public class BaseViewModel : INotifyPropertyChanged
{

    /// <summary>
    ///     Worker function used to set local fields and trigger an OnPropertyChanged event
    /// </summary>
    /// <typeparam name="T">Parameter class</typeparam>
    /// <param name="backingStore">Backing field referred to</param>
    /// <param name="value">New value</param>
    /// <param name="propertyName">Property that this value is applied to </param>
    /// <param name="onChanged">Event handler to invoke on value change</param>
    /// <param name="onChanging">Event handler to invoke on value changing</param>
    /// <returns></returns>
    protected bool SetProperty<T>(
        ref T backingStore, T value,
        [CallerMemberName] string propertyName = "",
        Action onChanged = null,
        Action<T> onChanging = null)
    {
        if (EqualityComparer<T>.Default.Equals(backingStore, value)) return false;

        onChanging?.Invoke(value);
        OnPropertyChanging(propertyName);

        backingStore = value;
        onChanged?.Invoke();
        OnPropertyChanged(propertyName);
        return true;
    }


    #region INotifyPropertyChanging implementation
    /// <summary>
    /// INotifyPropertyChanging event handler 
    /// </summary>
    public event PropertyChangingEventHandler PropertyChanging;

    /// <summary>
    /// INotifyOnPropertyChanging implementation
    /// </summary>
    /// <param name="propertyName">Class property that is changing</param>
    protected void OnPropertyChanging([CallerMemberName] string propertyName = "")
    {
        var changing = PropertyChanging;

        changing?.Invoke(this, new PropertyChangingEventArgs(propertyName));
    }

    #endregion

    #region INotifyPropertyChanged
    /// <summary>
    /// INotifyPropertyChanged event handler
    /// </summary>
    public event PropertyChangedEventHandler PropertyChanged;

    /// <summary>
    /// INotifyPropertyChanged implementation
    /// </summary>
    /// <param name="propertyName">Class property that has changed</param>
    protected void OnPropertyChanged([CallerMemberName] string propertyName = "")
    {
        var changed = PropertyChanged;

        changed?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }

    #endregion
}

Example of use:

public class SomeViewModel: BaseViewModel
{
    private int _someValue;

    public int SomeValue
    {
        get => _someValue;
        set => SetProperty(ref _someValue, value);
    }
}