I am trying to create an ObservableConcurrentDictionary. This object will be used in a multi-threaded application, and its data is used to populate the control through the ItemsSource property of the controls.
This is the implementation I came across:
public sealed class ObservableConcurrentDictionary<TKey, TValue> : ConcurrentDictionary<TKey, TValue>, INotifyCollectionChanged, INotifyPropertyChanged { #region Constructors public ObservableConcurrentDictionary() : base() { } public ObservableConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection) : base(collection) { } public ObservableConcurrentDictionary(IEqualityComparer<TKey> comparer) : base(comparer) { } public ObservableConcurrentDictionary(int concurrencyLevel, int capacity) : base(concurrencyLevel, capacity) { } public ObservableConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer) : base(collection, comparer) { } public ObservableConcurrentDictionary(int concurrencyLevel, int capacity, IEqualityComparer<TKey> comparer) : base(concurrencyLevel, capacity, comparer) { } public ObservableConcurrentDictionary(int concurrencyLevel, IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer) : base(concurrencyLevel, collection, comparer) { } #endregion #region Public Methods public new TValue AddOrUpdate(TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory) { // Stores the value TValue value; // If key exists if (base.ContainsKey(key)) { // Update value and raise event value = base.AddOrUpdate(key, addValueFactory, updateValueFactory); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace)); } // Else if key does not exist else { // Add value and raise event value = base.AddOrUpdate(key, addValueFactory, updateValueFactory); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add)); } // Returns the value return value; } public void Clear() { // Clear dictionary base.Clear(); // Raise event OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } public new TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory) { // Stores the value TValue value; // If key exists if (base.ContainsKey(key)) // Get value value = base.GetOrAdd(key, valueFactory); // Else if key does not exist else { // Add value and raise event value = base.GetOrAdd(key, valueFactory); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add)); } // Return value return value; } public new TValue GetOrAdd(TKey key, TValue value) { // If key exists if (base.ContainsKey(key)) // Get value base.GetOrAdd(key, value); // Else if key does not exist else { // Add value and raise event base.GetOrAdd(key, value); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add)); } // Return value return value; } public new bool TryAdd(TKey key, TValue value) { // Stores tryAdd bool tryAdd; // If added if (tryAdd = base.TryAdd(key, value)) // Raise event OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add)); // Return tryAdd return tryAdd; } public new bool TryRemove(TKey key, out TValue value) { // Stores tryRemove bool tryRemove; // If removed if (tryRemove = base.TryRemove(key, out value)) // Raise event OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove)); // Return tryAdd return tryRemove; } public bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue) { // Stores tryUpdate bool tryUpdate; // If updated if (tryUpdate = base.TryUpdate(key, newValue, comparisonValue)) // Raise event OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace)); // Return tryUpdate return tryUpdate; } #endregion #region Private Methods private void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { if (CollectionChanged != null) CollectionChanged(this, e); } #endregion #region INotifyCollectionChanged Members public event NotifyCollectionChangedEventHandler CollectionChanged; #endregion #region INotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; #endregion }
Unfortunately, the solution does not work properly - in fact, it does not work at all. Any ideas on what I am doing wrong or are there any better solutions?
Note that I CANNOT USE an ObservableCollection, so I need to write my own Observable collection.
EDIT: The working version is below. Hope this helps someone else with a similar issue.
public sealed class ObservableConcurrentDictionary<TKey, TValue> : ConcurrentDictionary<TKey, TValue>, INotifyCollectionChanged, INotifyPropertyChanged { public ObservableConcurrentDictionary() : base() { } public ObservableConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection) : base(collection) { } public ObservableConcurrentDictionary(IEqualityComparer<TKey> comparer) : base(comparer) { } public ObservableConcurrentDictionary(int concurrencyLevel, int capacity) : base(concurrencyLevel, capacity) { } public ObservableConcurrentDictionary(IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer) : base(collection, comparer) { } public ObservableConcurrentDictionary(int concurrencyLevel, int capacity, IEqualityComparer<TKey> comparer) : base(concurrencyLevel, capacity, comparer) { } public ObservableConcurrentDictionary(int concurrencyLevel, IEnumerable<KeyValuePair<TKey, TValue>> collection, IEqualityComparer<TKey> comparer) : base(concurrencyLevel, collection, comparer) { } public new TValue AddOrUpdate(TKey key, Func<TKey, TValue> addValueFactory, Func<TKey, TValue, TValue> updateValueFactory) { // Stores the value TValue value; // If key exists if (base.ContainsKey(key)) { // Update value and raise event value = base.AddOrUpdate(key, addValueFactory, updateValueFactory); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, value)); } // Else if key does not exist else { // Add value and raise event value = base.AddOrUpdate(key, addValueFactory, updateValueFactory); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, value)); } // Returns the value return value; } public new void Clear() { // Clear dictionary base.Clear(); // Raise event OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); } public new TValue GetOrAdd(TKey key, Func<TKey, TValue> valueFactory) { // Stores the value TValue value; // If key exists if (base.ContainsKey(key)) // Get value value = base.GetOrAdd(key, valueFactory); // Else if key does not exist else { // Add value and raise event value = base.GetOrAdd(key, valueFactory); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, value)); } // Return value return value; } public new TValue GetOrAdd(TKey key, TValue value) { // If key exists if (base.ContainsKey(key)) // Get value base.GetOrAdd(key, value); // Else if key does not exist else { // Add value and raise event base.GetOrAdd(key, value); OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, value)); } // Return value return value; } public new bool TryAdd(TKey key, TValue value) { // Stores tryAdd bool tryAdd; // If added if (tryAdd = base.TryAdd(key, value)) // Raise event OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, value)); // Return tryAdd return tryAdd; } public new bool TryRemove(TKey key, out TValue value) { // Stores tryRemove bool tryRemove; // If removed if (tryRemove = base.TryRemove(key, out value)) // Raise event OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, value)); // Return tryAdd return tryRemove; } public new bool TryUpdate(TKey key, TValue newValue, TValue comparisonValue) { // Stores tryUpdate bool tryUpdate; // If updated if (tryUpdate = base.TryUpdate(key, newValue, comparisonValue)) // Raise event OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newValue)); // Return tryUpdate return tryUpdate; } private void OnCollectionChanged(NotifyCollectionChangedEventArgs e) { if (CollectionChanged != null) CollectionChanged(this, e); } public event NotifyCollectionChangedEventHandler CollectionChanged; public event PropertyChangedEventHandler PropertyChanged; }