This is something I wrote for an application I’m developing. This is an implementation of INotifyPropertyChanged that requires no backing fields, just call Set(value) or Get(). Internally it uses a dictionary to store the state and even reuses ChangedEventArgs
The source code can be found at:
https://github.com/ebalynn/StatefulViewModel/
Here is the extract from the ViewModel class that does all the heavy lifting:
using System; using System.Collections.Concurrent; using System.ComponentModel; using System.Runtime.CompilerServices; using System.Threading; namespace Balynn.xxx { public abstract class ViewModel : INotifyPropertyChanged { private readonly Lazy<ConcurrentDictionary<string, object>> _propertyRefValues = new Lazy<ConcurrentDictionary<string, object>>(LazyThreadSafetyMode.ExecutionAndPublication); private readonly Lazy<ConcurrentDictionary<string, PropertyChangedEventArgs>> _propertyChangedEventArgs = new Lazy<ConcurrentDictionary<string, PropertyChangedEventArgs>>(); public event PropertyChangedEventHandler PropertyChanged; protected virtual T Get<T>(T defaultValue = default, [CallerMemberName] string propertyName = null) { if (_propertyRefValues.Value.ContainsKey(propertyName)) { return (T) _propertyRefValues.Value[propertyName]; } return defaultValue; } protected virtual bool Set<T>(T value, [CallerMemberName] string propertyName = null) { var existing = Get(default(T), propertyName); if (object.Equals(existing, value) == false) { _propertyRefValues.Value[propertyName] = value; RaisePropertyChanged(propertyName); return true; } return false; } protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null) { var propertyArgs = _propertyChangedEventArgs.Value .GetOrAdd(propertyName, new PropertyChangedEventArgs(propertyName)); PropertyChanged?.Invoke(this, propertyArgs); } } }
Leave a Reply