J'essaie de créer un ObservableConcurrentDictionary. Cet objet sera utilisé dans une application multithread et ses données sont utilisées pour remplir un contrôle via la propriété ItemsSource des contrôles.Comment créer une collection observable personnalisée à l'aide de ConcurrentDictionary, INotifyCollectionChanged, INotifyPropertyChanged
C'est la mise en œuvre, je suis venu avec:
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
}
Malheureusement, la solution ne fonctionne pas comme prévu - en fait, il ne fonctionne pas du tout. Des idées sur ce que je fais de mal ou de faire de meilleures solutions existent?
Veuillez noter que je ne peux pas utiliser ObservableCollection, par conséquent je dois écrire ma propre collection Observable.
EDIT: La version de travail est ci-dessous. J'espère que cela aide quelqu'un d'autre avec un problème similaire.
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;
}
"cela ne fonctionne pas du tout" - n'est pas une description de problème valide. Dites-nous quelles erreurs obtenez-vous, quel code utilisez-vous pour le tester et pourquoi vous ne pouvez pas utiliser ObservableCollection? – Euphoric