using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Runtime.CompilerServices; namespace HavenSoft.HexManiac.Core.ViewModels { public class ViewModelCore : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; protected void NotifyPropertyChanged([CallerMemberName]string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } protected void NotifyPropertyChanged(object oldValue, [CallerMemberName]string propertyName = null) { PropertyChanged?.Invoke(this, new ExtendedPropertyChangedEventArgs(oldValue, propertyName)); } /// /// Utility function to make writing property updates easier. /// If the backing field's value does not match the new value, the backing field is updated and PropertyChanged gets called. /// /// The type of the property being updated. /// A reference to the backing field of the property being changed. /// The new value for the property. /// The name of the property to notify on. If the property is the caller, the compiler will figure this parameter out automatically. /// false if the data did not need to be updated, true if it did. protected bool TryUpdate(ref T backingField, T newValue, [CallerMemberName]string propertyName = null) where T : IEquatable { if (backingField == null && newValue == null) return false; if (backingField != null && backingField.Equals(newValue)) return false; var oldValue = backingField; backingField = newValue; NotifyPropertyChanged(oldValue, propertyName); return true; } protected bool TryUpdateEnum(ref T backingField, T newValue, [CallerMemberName]string propertyName = null) where T : Enum { if (backingField.Equals(newValue)) return false; var oldValue = backingField; backingField = newValue; NotifyPropertyChanged(oldValue, propertyName); return true; } protected bool TryUpdateSequence(ref T backingField, T newValue, [CallerMemberName]string propertyName = null) where T : IEnumerable where U : IEquatable { if (backingField == null && newValue == null) return false; if (backingField != null && backingField.Count() == newValue.Count()) { bool allMatch = true; foreach (var pair in backingField.Zip(newValue, (a, b) => (a, b))) { if (pair.a.Equals(pair.b)) continue; allMatch = false; break; } if (allMatch) return false; } var oldValue = backingField; backingField = newValue; NotifyPropertyChanged(oldValue, propertyName); return true; } } public class ExtendedPropertyChangedEventArgs : PropertyChangedEventArgs { public object OldValue { get; } public ExtendedPropertyChangedEventArgs(object oldValue, string propertyName) : base(propertyName) => OldValue = oldValue; } }