#region License Information /* HeuristicLab * Copyright (C) 2002-2019 Heuristic and Evolutionary Algorithms Laboratory (HEAL) * * This file is part of HeuristicLab. * * HeuristicLab is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * HeuristicLab is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with HeuristicLab. If not, see . */ #endregion using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using HEAL.Attic; namespace HeuristicLab.Collections { [StorableType("EFAF5129-39F0-4477-834E-E22B85D63BCF")] [Serializable] public class ObservableDictionary : IObservableDictionary { [Storable] protected Dictionary dict; #region Properties public ICollection Keys { get { return dict.Keys; } } public ICollection Values { get { return dict.Values; } } public int Count { get { return dict.Count; } } public IEqualityComparer Comparer { get { return dict.Comparer; } } bool ICollection>.IsReadOnly { get { return ((ICollection>)dict).IsReadOnly; } } public TValue this[TKey key] { get { return dict[key]; } set { if (dict.ContainsKey(key)) { KeyValuePair item = new KeyValuePair(key, dict[key]); dict[key] = value; OnItemsReplaced(new KeyValuePair[] { new KeyValuePair(key, value) }, new KeyValuePair[] { item }); } else { dict[key] = value; OnItemsAdded(new KeyValuePair[] { new KeyValuePair(key, value) }); } } } #endregion #region Constructors public ObservableDictionary() { dict = new Dictionary(); } public ObservableDictionary(int capacity) { dict = new Dictionary(capacity); } public ObservableDictionary(IEqualityComparer comparer) { dict = new Dictionary(comparer); } public ObservableDictionary(IDictionary dictionary) { dict = new Dictionary(dictionary); } public ObservableDictionary(int capacity, IEqualityComparer comparer) { dict = new Dictionary(capacity, comparer); } public ObservableDictionary(IDictionary dictionary, IEqualityComparer comparer) { dict = new Dictionary(dictionary, comparer); } [StorableConstructor] protected ObservableDictionary(StorableConstructorFlag _) { } #endregion #region Access public bool ContainsKey(TKey key) { return dict.ContainsKey(key); } public bool ContainsValue(TValue value) { return dict.ContainsValue(value); } bool ICollection>.Contains(KeyValuePair item) { return dict.Contains(item); } public bool TryGetValue(TKey key, out TValue value) { return dict.TryGetValue(key, out value); } #endregion #region Manipulation public void Add(TKey key, TValue value) { dict.Add(key, value); OnPropertyChanged("Item[]"); OnPropertyChanged("Keys"); OnPropertyChanged("Values"); OnPropertyChanged("Count"); OnItemsAdded(new KeyValuePair[] { new KeyValuePair(key, value) }); } void ICollection>.Add(KeyValuePair item) { ((ICollection>)dict).Add(item); OnPropertyChanged("Item[]"); OnPropertyChanged("Keys"); OnPropertyChanged("Values"); OnPropertyChanged("Count"); OnItemsAdded(new KeyValuePair[] { item }); } public bool Remove(TKey key) { TValue value; if (dict.TryGetValue(key, out value)) { dict.Remove(key); OnPropertyChanged("Item[]"); OnPropertyChanged("Keys"); OnPropertyChanged("Values"); OnPropertyChanged("Count"); OnItemsRemoved(new KeyValuePair[] { new KeyValuePair(key, value) }); return true; } return false; } bool ICollection>.Remove(KeyValuePair item) { if (((ICollection>)dict).Remove(item)) { OnPropertyChanged("Item[]"); OnPropertyChanged("Keys"); OnPropertyChanged("Values"); OnPropertyChanged("Count"); OnItemsRemoved(new KeyValuePair[] { item }); return true; } return false; } public void Clear() { if (dict.Count > 0) { KeyValuePair[] items = dict.ToArray(); dict.Clear(); OnPropertyChanged("Item[]"); OnPropertyChanged("Keys"); OnPropertyChanged("Values"); OnPropertyChanged("Count"); OnCollectionReset(new KeyValuePair[0], items); } } #endregion #region Conversion public ReadOnlyObservableDictionary AsReadOnly() { return new ReadOnlyObservableDictionary(this); } void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) { ((ICollection>)dict).CopyTo(array, arrayIndex); } #endregion #region Enumeration public IEnumerator> GetEnumerator() { return dict.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return dict.GetEnumerator(); } #endregion #region Events [field: NonSerialized] public event CollectionItemsChangedEventHandler> ItemsAdded; protected virtual void OnItemsAdded(IEnumerable> items) { CollectionItemsChangedEventHandler> handler = ItemsAdded; if (handler != null) handler(this, new CollectionItemsChangedEventArgs>(items)); } [field: NonSerialized] public event CollectionItemsChangedEventHandler> ItemsRemoved; protected virtual void OnItemsRemoved(IEnumerable> items) { CollectionItemsChangedEventHandler> handler = ItemsRemoved; if (handler != null) handler(this, new CollectionItemsChangedEventArgs>(items)); } [field: NonSerialized] public event CollectionItemsChangedEventHandler> ItemsReplaced; protected virtual void OnItemsReplaced(IEnumerable> items, IEnumerable> oldItems) { CollectionItemsChangedEventHandler> handler = ItemsReplaced; if (handler != null) handler(this, new CollectionItemsChangedEventArgs>(items, oldItems)); } [field: NonSerialized] public event CollectionItemsChangedEventHandler> CollectionReset; protected virtual void OnCollectionReset(IEnumerable> items, IEnumerable> oldItems) { CollectionItemsChangedEventHandler> handler = CollectionReset; if (handler != null) handler(this, new CollectionItemsChangedEventArgs>(items, oldItems)); } [field: NonSerialized] public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged(string propertyName) { PropertyChangedEventHandler handler = PropertyChanged; if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); } #endregion } }