using System.Collections; using System.Collections.Generic; using System.Collections.Specialized; using System.ComponentModel; using System.Linq; namespace StabilityMatrix.Avalonia.Models; public class ObservableDictionary : ICollection>, IDictionary, INotifyCollectionChanged, INotifyPropertyChanged where TKey : notnull { protected readonly IDictionary dictionary; public event NotifyCollectionChangedEventHandler? CollectionChanged; public event PropertyChangedEventHandler? PropertyChanged; public IEnumerator> GetEnumerator() => dictionary.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); public ObservableDictionary() { dictionary = new Dictionary(); } public ObservableDictionary(Dictionary dictionary) { this.dictionary = dictionary; } public void Add(KeyValuePair item) { dictionary.Add(item); CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, item)); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Keys))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Values))); } public void Clear() { dictionary.Clear(); CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Keys))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Values))); } public bool Contains(KeyValuePair item) => dictionary.Contains(item); public void CopyTo(KeyValuePair[] array, int arrayIndex) { dictionary.CopyTo(array, arrayIndex); } public bool Remove(KeyValuePair item) { var success = dictionary.Remove(item); if (!success) return false; CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, item)); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Keys))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Values))); return success; } public int Count => dictionary.Count; public bool IsReadOnly => dictionary.IsReadOnly; public void Add(TKey key, TValue value) { dictionary.Add(key, value); CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new KeyValuePair(key, value))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Keys))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Values))); } public bool ContainsKey(TKey key) => dictionary.ContainsKey(key); public bool Remove(TKey key) { var success = dictionary.TryGetValue(key, out var value) && dictionary.Remove(key); if (!success) return false; CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new KeyValuePair(key, value))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Keys))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Values))); return success; } public bool TryGetValue(TKey key, out TValue value) => dictionary.TryGetValue(key, out value); public TValue this[TKey key] { get => dictionary[key]; set { var exists = dictionary.ContainsKey(key); var action = exists ? NotifyCollectionChangedAction.Replace : NotifyCollectionChangedAction.Add; dictionary[key] = value; CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(action, dictionary[key])); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Count))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Keys))); PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(Values))); } } public ICollection Keys => dictionary.Keys; public ICollection Values => dictionary.Values; }