Craigomatic

Im having trouble getting an observable dictionary wrapper class to work. The add part of it works fine, my problem is at the remove method.

My class looks something like this:

public class ThreadSafeDictionary<TKey, TValue> : INotifyCollectionChanged, INotifyPropertyChanged

{

private Dictionary<TKey, TValue> _Dictionary;

public void Add(TKey key, TValue value)

{

_Dictionary.Add(key, value);

OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new KeyValuePair<TKey, TValue>(key, value)));

OnPropertyChanged("Keys");

OnPropertyChanged("Values");

OnPropertyChanged("Count");

}

public void Remove(TKey key)

{

_Dictionary.Remove(key);

//PROBLEM HERE! Which NotifyCollectionChangedEventArgs to use

OnPropertyChanged("Keys");

OnPropertyChanged("Values");

OnPropertyChanged("Count");

}

}

I've tried all combinations of NotifyCollectionChangedEventArgs construcors, but they all seem to give me an exception, and the overload that looks like its the correct one for the Remove event seems to want an integer when all I have is a TKey

Any help appreciated!



Re: Windows Presentation Foundation (WPF) Observable Dictionary, problem with Remove...

Yiling Lai

Hello, Did you have tried this way

Code Snippet

public void Remove(TKey key)
{
TValue value = _Dictionary[key];
_Dictionary.Remove(key);

OnCollectionChanged(new NotifyCollectionChangedEventArgs(

NotifyCollectionChangedAction.Remove,

new KeyValuePair<TKey, TValue>(key, value)));

...
}

Also, this thread may helpful for you.






Re: Windows Presentation Foundation (WPF) Observable Dictionary, problem with Remove...

Craigomatic

Thanks for the reply Yiling, I tried as you suggested and I get this error on my event invocation:

Collection Remove event must specify item position.

My code in that section looks like this:

Code Snippet

public event NotifyCollectionChangedEventHandler CollectionChanged;

protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e)

{

NotifyCollectionChangedEventHandler handler = CollectionChanged;

if (handler != null)

handler(this, e);

}





Re: Windows Presentation Foundation (WPF) Observable Dictionary, problem with Remove...

Dr. WPF

To truly be a dictionary and truly be observable, you must implement the following interfaces:

[Serializable]

public class ObservableDictionary< TKey, TValue > :

IDictionary< TKey, TValue >,

ICollection< KeyValuePair< TKey, TValue > >,

IEnumerable< KeyValuePair< TKey, TValue > >,

IDictionary,

ICollection,

IEnumerable,

ISerializable,

IDeserializationCallback,

INotifyCollectionChanged,

INotifyPropertyChanged

None of these interfaces are indexed by integer, but unfortunately, observable collections are.

In your example, you are trying to create an observable collection by aggregating a Dictionary. This won't work because none of the public interfaces expose the index of entries within the dictionary's internal collection.

Dictionaries basically work by aggregating an internal collection of DictionaryEntry values. This collection is usually of type KeyedCollection< TKey, DictionaryEntry >. When you fire your collection change notification for the Remove action, you need to supply both the DictionaryEntry value and the index of that value within the aggregate collection.

So rather than aggregate a Dictionary, you will need to aggregate a KeyedCollection, just as the standard Dictionary template class does. Unfortunately, this means you must also implement all of the interfaces listed above, which involves a lot of grunt work.

You are already firing the correct property changes in your Remove() function. Your collection change code should look something like this:

Code Snippet

DictionaryEntry entry = _aggregateCollection[key];

int index = _aggregateCollection.IndexOf(key);

if (index > -1)

{

OnCollectionChanged(new NotifyCollectionChangedEventArgs(

NotifyCollectionChangedAction.Remove, entry, index));

}

else

{

OnCollectionChanged(new NotifyCollectionChangedEventArgs(

NotifyCollectionChangedAction.Reset));

}






Re: Windows Presentation Foundation (WPF) Observable Dictionary, problem with Remove...

Yiling Lai

For remove event, you can try this:

OnCollectionChanged(new NotifyCollectionChangedEventArgs(

NotifyCollectionChangedAction.Remove,

new KeyValuePair<TKey, TValue>(key, value), -1));






Re: Windows Presentation Foundation (WPF) Observable Dictionary, problem with Remove...

Dr. WPF

If the collection is bound to an items source and you issue a Remove action with an index of -1, you will cause an exception. The index must be greater than or equal to 0 and less than the collection's count.

Note that collection change notifications exist as an optimization for keeping collection views in sync with databound collections. The code that monitors these events expects to map the supplied index to an item in the view. Although you could issue a Reset action when a single item is removed, this defeats the purpose and would cause the entire view to be regenerated.






Re: Windows Presentation Foundation (WPF) Observable Dictionary, problem with Remove...

Dr. WPF

I've posted an Observable Dictionary Sample for anyone who might be interested.