Despite the fact that in this solution the event is still propagating from the setter (so that's not what it is all about), it provides a good, more manageable way of representing dependencies. Someone may find this helpful.
The solution is to create a custom wrapper to fire INotifyPropertyChanged events. Instead of calling OnPropertyChanged manually, we can define the following mathods (preferably inside the base class, which we will use later):
public abstract class ViewModelBase : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; internal void OnPropertyChanged(string propertyName) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected ViewModelPropertyChange SetPropertyValue<T>(ref T property, T value, [CallerMemberName] string propertyName = null) { property = value; OnPropertyChanged(propertyName); return new ViewModelPropertyChange(this); } }
This class provides us with a way to set the value of this field without having to provide the name of the partisan call coming from.
We also need to define a class that we can use to define dependent properties (an instance of this class is returned from SetPropertyValue mathod).
public class ViewModelPropertyChange { private readonly ViewModelBase _viewModel; public ViewModelPropertyChange(ViewModelBase viewModel) { _viewModel = viewModel; } public ViewModelPropertyChange WithDependent(string name) { _viewModel.OnPropertyChanged(name); return this; } }
It simply stores a reference to the object that is being modified, and allows you to extend the event to the following properties.
With this, we can create a class derived from ViewModelBase, like this:
class OurViewModel : ViewModelBase { private int _partOne; public int PartOne { get => _partOne; set => SetPropertyValue(ref _partOne, value) .WithDependent(nameof(Total)); } private int _partTwo; public int PartTwo { get => _partTwo; set => SetPropertyValue(ref _partTwo, value) .WithDependent(nameof(Total)) .WithDependent(nameof(PartTwoPlus2)); } public int Total { get => PartOne + PartTwo; } public int PartTwoPlus2 { get => PartTwo + 2; } }
source share