C# 6.0 – INotifyPropertyChanged – Eine Basis für ein ViewModel

Mit C# 6.0 hat sich viel geändert und vor allem verbessert. So auch die Möglichkeit die Schnittstelle INotifyPropertyChanged einzubinden. Hier bekommt man zwar von der aktuellen ReSharper Version eine schöne Unterstützung, aber wer mehr will, muss noch Hand anlegen. Ich habe in diesem Video das Ganze soweit entwickelt, dass Properties direkt in einem Dictionary gespeichert werden und somit für den Quellcode schlanker aussehen. Trotz einiger Versprecher und Vertipper hier das Video zur Implementierung:


 

Anschließend hier noch der Quellcode zum Video:

class Program
{
    static void Main(string[] args)
    {
        MyViewModel viewModel = new MyViewModel();
        viewModel.Name = "Hello World 123";
        viewModel.Name = "Hello 123";
        viewModel.Name = "World 123";

        Console.ReadLine();
    }
}

public class MyViewModel : ViewModelBase
{
    public string Name
    {
        get { return GetValue<string>(); }
        set { SetValue(value, OnValueSet); }
    }

    private void OnValueSet()
    {
        Console.WriteLine(Name);
    }
}

public abstract class ViewModelBase : INotifyPropertyChanged
{
    private readonly Dictionary<string, object> _propertyValues = new Dictionary<string, object>();

    public event PropertyChangedEventHandler PropertyChanged;

    protected TValue GetValue<TValue>(TValue defaultValue = default(TValue), [CallerMemberName] string propertyName = null)
    {
        string key = $"{typeof (TValue)}::{propertyName}";
        return _propertyValues.ContainsKey(key) ? (TValue) _propertyValues[key] : defaultValue;
    }

    protected void SetValue<TValue>(TValue value, Action callback = null, [CallerMemberName] string propertyName = null)
    {
        string key = $"{typeof(TValue)}::{propertyName}";
        if (_propertyValues.ContainsKey(key))
        {
            if (_propertyValues[key] != null && _propertyValues[key].Equals(value))
                return;

            IComparable comparableValue = value as IComparable;
            IComparable comparableDictionary = _propertyValues[key] as IComparable;
            if (comparableValue != null && comparableDictionary != null)
            {
                if (!Equals(comparableValue, comparableDictionary))
                {
                    _propertyValues[key] = value;
                    OnPropertyChanged(propertyName);
                }
            }
            else
            {
                _propertyValues[key] = value;
                OnPropertyChanged(propertyName);
            }
        }
        else
        {
            _propertyValues.Add(key, value);
            OnPropertyChanged(propertyName);
        }

        callback?.Invoke();
    }

    [NotifyPropertyChangedInvocator]
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}