What is the best way in c# to notify property changed on an item\'s field without set
but get
depends on other fields ?
For example :
Even though in this solution the event is still propagated from the setter (so not exactly what the question is about), it provides a nice, more manageable way for representing dependencies. Someone might find it useful.
The solution is to create a custom wrapper for triggering INotifyPropertyChanged events. Instead of calling OnPropertyChanged manually we can define following mathods (preferably inside a base class that we will reuse later):
public abstract class ViewModelBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
internal void OnPropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
protected ViewModelPropertyChange SetPropertyValue(ref T property, T value, [CallerMemberName] string propertyName = null)
{
property = value;
OnPropertyChanged(propertyName);
return new ViewModelPropertyChange(this);
}
}
This class provides us with a way of setting a value of a given field without a need for providing the name of a proparty the call comes from.
We also have to define a class that will enable use to define dependent properties (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 an object that is being changed and makes it possible to propagate an event to next 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;
}
}