Can I bind my ItemsControl to a dictionary?

I’ve seen a number of forum posts lately expressing a desire for an observable dictionary.  Here are links to a couple of them:

Thread 1: Observable Dictionary, problem with Remove

Thread 2: Bind observable dictionary

As promised in my response to the latter thread, I am now providing a sample demonstrating how one might implement an observable dictionary.  You can download the sample here.

The Observable Dictionary Sample

In this sample, I demonstrate how to bind to a dictionary of button styles.  The styles are sorted based on their Key values in the observable dictionary.  (Clearly, this should be treated as a nonsensical illustration for demonstration purposes only.)

On the left side of the window is a ListView that is bound to the observable dictionary.  If you click an odd-indexed button in the ListView, its corresponding entry is removed from the dictionary.  If you click an even-indexed button, its entry is duplicated in the dictionary.

On the right side of the window is a ComboBox whose items are bound to the same dictionary.  Beneath the ComboBox is a Button whose style is bound to the selected value of the ComboBox.  If you click this button, the dictionary will be cleared and reloaded.

As you click around, you will notice that the bound controls respond appropriately to any changes in the observable dictionary.

So why would someone want to do this?

Dictionaries are easy to work with in code.  Perhaps you’ve already written an application that leverages a dictionary to store and retrieve in-memory data.  You may now want to provide a view of the dictionary entries in your user interface. 

Unfortunately, to provide a dynamic view of your dictionary data, you would need to do a lot of extra work.  Namely, you would need to write code to synchronize some observable collection with your dictionary whenever you modify it. 

Wouldn’t it be nice if the dictionary, itself, were observable?

The Observable Dictionary Class

What we clearly need is an “observable” dictionary class.  You will find an example of such a class in the ObservableDictionary.cs file in the provided sample.  What does it mean for a dictionary to be observable?  In WPF, an observable class is simply a collection class that provides change notifications whenever its collection changes.  It does this by implementing the INotifyPropertyChanged and INotifyCollectionChanged interfaces.  This allows it to serve as the “ItemsSource” of a collection control (like a ListBox, ComboBox, or any other ItemsControl).  These controls know how to monitor the collection for changes.

For a detailed explanation of how binding to a collection works, see the MSDN documentation.  Here is a good starting point.

So how do you implement an observable dictionary?

Dictionaries basically work by aggregating an internal collection of key-value pairs.  People often start by trying to derive a class from Dictionary<TKey, TValue> or by trying to implement IDictionary<TKey, TValue> in a class that aggregates a dictionary.  The idea is that they could then add the requisite INotifyPropertyChanged and INotifyCollectionChanged interfaces and have an observable dictionary.

There’s a major problem with this approach.  Observable collections are indexed by integer.  In order to fire the necessary collection change notifications, you must know the index of an entry when it changes.  Unfortunately, none of the interfaces exposed by the Dictionary<TKey, TValue> class are indexed by integer.  And if you derive directly from Dictionary<TKey, TValue>, you do not have access to the underlying collection.  As a result, an attempt to create an observable dictionary by deriving from or aggregating a dictionary won’t work.

To truly create an observable dictionary, you need to aggregate your own collection (usually of type KeyedCollection<TKey, TValue>).  Then you must implement a whole slew of interfaces on top of the collection, as shown in the following class declaration:

    public class ObservableDictionary <TKey, TValue> :
        IDictionary<TKey, TValue>,
        ICollection<KeyValuePair<TKey, TValue>>,
        IEnumerable<KeyValuePair<TKey, TValue>>,
        IDictionary,
        ICollection,
        IEnumerable,
        ISerializable,
        IDeserializationCallback,
        INotifyCollectionChanged,
        INotifyPropertyChanged

By implementing all of the above interfaces, you ensure that your dictionary class can be used interchangeably with the CLR’s Dictionary class.  You should only need to change the declaration from Dictionary<TKey, TValue> to ObservableDictionary<TKey, TValue> in your code.

Pros and Cons

The benefit to using an observable dictionary, of course, is that the dictionary can serve as the ItemsSource for a databound control and you can still access the dictionary in code the same way you access any other dictionary.  It is truly an indexed dictionary of objects.

There are certainly some limitations inherent in the very idea of making a dictionary observable.  Dictionaries are built for speed.  When you impose the behaviors of an observable collection on a dictionary so that the framework can bind to it, you add overhead.

Also, a dictionary exposes its Values and Keys collections through separate properties of the same name.  These collections are of types Dictionary<TKey, TValue>.ValueCollection and Dictionary<TKey, TValue>.KeyCollection, respectively.  These CLR-defined collections are not observable.  As such, you cannot bind to the Values collection or to the Keys collection directly and expect to receive dynamic collection change notifications.  You must instead bind directly to the observable dictionary.

The Observable Sorted Dictionary Class

Another thing to note is that a dictionary doesn’t typically store its data in a deterministic order.  When binding to an observable dictionary, you cannot simply apply a sort order via a CollectionView because the exposed interfaces do not support sorting.  For this reason, I include an ObservableSortedDictionary class in the attached sample.

Binding to an Observable Dictionary

When you bind to an observable dictionary, you are really binding to a collection of KeyValuePair objects. A KeyValuePair is an object which makes the entry’s key available via an appropriately named Key property and its value available via a Value property.  Your item templates must take this into consideration and provide the appropriate binding paths.  The provided sample illustrates how to do this.

All the Standard Caveats Apply

As always, this sample is provided “as is”.  It has not been heavily tested and there are probably lots of improvements that could be made.  Use it and modify it as you see fit.  Let me know how it works for you, what improvements you make, what bugs you find, etc.

Cheers,
Dr. WPF

60 Responses to “Can I bind my ItemsControl to a dictionary?”

  1. Nathan says:

    bug in the IDictionary index property… recursive calls == stack overflow

    this was my simple fix:

    object IDictionary.this[object key]
    {
    get { return ((IDictionary)this)[(TKey)key]; }
    set { DoSetEntry((TKey)key, (TValue)value); }
    }

  2. Dr. WPF says:

    Great catch, Nathan! I have added the fix to the sample. Much thanks! -dw

  3. marco.ragogna says:

    I was planning to create by myself but a brief search in google take me here. Thanks for the code I will try it and come back if I find some suggestion or problem

    thank you for sharing

  4. Rodrigo says:

    Hi,
    I’m having trouble sorting the ObservableSortedDictionary. I create a CollectionViewSource bound to the ObservableSortedDictionary, and create a ListBox which binds to the CollectionViewSource. This works fine, and all the items in the collection are displayed as expected. However when I add some sort descriptions as follows:
    <CollectionViewSource.SortDescriptions>
    <scm:SortDescription PropertyName=”Key” Direction=”Ascending” />
    </CollectionViewSource.SortDescriptions>
    I get an InvalidOperationException (‘System.Windows.Data.CollectionView’ view does not support sorting.) What am I doing wrong?

    Any help would be much appreciated! Thanks,

    Rod

  5. Dr. WPF says:

    Hi Rod,

    Sorry. I really should have been more clear in my description of the sorted dictionary class.

    Just like the standard dictionary, this class does not support sorting via a CollectionView. Rather, it provides a dictionary that stores its items already sorted. You must supply an IComparer instance when constructing the class. Clearly, this adds some overhead to the dictionary.

    You would only use a sorted dictionary if you knew that you would be binding to it and you needed the bound items to appear in a certain order. This is no where near as convenient as the CollectionView approach where you are really only sorting a view of the items. Again, a dictionary does not lend itself nicely to such an approach, since it is really built for speed.

    Cheers,
    -dw

  6. marco.ragogna says:

    Hi Dr.Wpf,
    you’re class is really interesting and helpful.
    I found only a small bug in it but I am not really sure how to solve it.

    Maybe you can help me…

    The problem happens when I try to iterate in the ObservableDictionary collection.

    For example the following code:

    obsDictionary.Last().Value

    return me the following expcetion:

    Unable to cast object of type ‘Enumerator[System.Collections.DictionaryEntry]’ to type ‘System.Collections.Generic.IEnumerator`1[System.Collections.Generic.KeyValuePair`2[System.String,System.Int32]]’.

    locate in

    IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
    {
    return (IEnumerator<KeyValuePair<TKey, TValue>>)GetEnumerator();
    }

    do you have any idea. If you prefer to not use the blog as support I can make the question in the MSDN forum 😉

    Thank you

  7. Dr. WPF says:

    Thx Marco. Yes, that’s a bug… I was a bit too hasty in completing some of the interfaces. That line should read as follows:

    return (IEnumerator<KeyValuePair<TKey, TValue>>)TrueDictionary.GetEnumerator();

    I’ve updated the code in the sample. Keep me posted if you encounter any more such issues. 🙂

    Thanks again!
    -dw

  8. marco.ragogna says:

    Thanks a lot for your help, this class if very useful. Unfortunately for me I discover yesterday that I cannot use it in my current project.

    The problem I discovered is that I cannot bind in TwoWay mode the Key and Value properties of ObservableDictionary items because they are, of course (but I didn’t know before yesterday 🙂 ) ReadOnly because part of structure KeyValuePair.

    In any case this is indeed a very nice class that I will use in other projects.

    Keep up the good work you are doing in sharing WPF code and hints.

  9. Paul says:

    This is probably highlighting my lack of low down knowlage on the subject, but, when binding an Infragistics xamDataGrid control to your ObservableDictionary only the type of the value is displayed where as using a standard Dictionary object the value (in this case a List (Of T) object) is fully enumerated. Is this one of the limitations of making the Dictionary observable?

    Many thanks

  10. Dr. WPF says:

    Hi Paul,

    This class should behave in the same manner as a native dictionary when used as the source for a collection binding (unless the control is designed to behave differently when bound to a dictionary).

    If you can send me a simple repro that demonstrates the difference you’re seeing, I’d be willing to take a look.

    Cheers,
    -dw

  11. Dr. WPF says:

    Hi Paul,

    Thanks so much for sending the sample application! You were absolutely correct! The default enumerator for the native Dictionary class returns KeyValuePair objects, whereas my enumerator was returning DictionaryEntry objects.

    I have updated the code to include a custom enumerator so that it behaves just like the native class. Please give this a try and let me know if it works better for you.

    Thanks again for helping me make this code better!
    -dw

  12. Nicole Taylor says:

    I am also trying to bind a combo box control to an ObservableDictionary. Everything shows fine based on the code below. I am coding everything in the code behind because my XAML developer uses Expression Blend and we have trouble going back and forth between Visual Studio and Expression Blend. When I change the selection in the combo box, the OnPropertyChanged(string name) is called but the string "name" is always null. Also, when I add a new KeyValue to the collection, the combo box doesn’t show the new entry even though it is successfully added to the dictionary. I am pretty sure I am not binding to the Dictionary properly (as you can see from the my commented code I am trying several different methods). I am wondering if you have any suggestions for doing all this binding in the code behind.Thanks,Nicole

    Binding binding1 = new Binding("UserTypeName");
    binding1.Source = UserTypes.Values;
    binding1.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
    binding1.Mode = BindingMode.TwoWay;
      //_cmbUserTypes.SetBinding(ItemsControl.ItemsSourceProperty, binding1);
    //_cmbUserTypes.SetBinding(ItemsControl.DisplayMemberPathProperty, "UserTypeName");
    //_cmbUserTypes.SetBinding(System.Windows.Controls.Primitives.Selector.SelectedValuePathProperty, "UserTypeID");
      _cmbUserTypes.ItemsSource = UserTypes.Values;
    _cmbUserTypes.DisplayMemberPath = "UserTypeName";
    _cmbUserTypes.SelectedValuePath = "UserTypeID";
      //_cmbUserTypes.SetBinding(System.Windows.Controls.Primitives.Selector.SelectedItemProperty, binding1);

  13. Dr. WPF says:

    Hi Nicole,

    I’m not sure I fully understand what you’re trying to do in the code snippet, but I do notice that you’re setting the source of the binding to be the Values collection. As I mentioned in the article, the Values collection is not observable. The source must be the ObservableDictionary itself. binding1.Source = UserTypes;

    I don’t think you want a two-way binding. There’s no way to add entries to the dictionary automatically if entries are added to the ComboBox.

    You probably want to set the binding via your first example: _cmbUserTypes.SetBinding(ItemsControl.ItemsSourceProperty, binding1);

    I would need to see a full repro to really understand your scenario.

  14. Martin says:

    Hello Dr. WPF !

    First of all, thank you for your ObservableDictionary class. I really like it since it helps to keep my code clean! In my project, I bind a WPF TreeView control to the ObservableDictionary and it works perfectly, except for one operation : Remove.

    It crashes on this line :
    OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, entry, index));

    With this exception/stack trace :

    System.InvalidOperationException was unhandled
      Message="Added item does not appear at given index ‘4’."
      Source="PresentationFramework"
      StackTrace:
         at MS.Internal.Data.EnumerableCollectionView.ProcessCollectionChanged(NotifyCollectionChangedEventArgs args)
         at System.Windows.Data.CollectionView.OnCollectionChanged(Object sender, NotifyCollectionChangedEventArgs args)
         at Collections.ObservableDictionary`2.OnCollectionChanged(NotifyCollectionChangedEventArgs args) in D:ProjetsCollectionsObservableDictionary.cs:line 199
         at Collections.ObservableDictionary`2.FireEntryRemovedNotifications(DictionaryEntry entry, Int32 index) in D:ProjetsCollectionsObservableDictionary.cs:line 311
         at Collections.ObservableDictionary`2.DoRemoveEntry(TKey key) in D:ProjetsCollectionsObservableDictionary.cs:line 267
         at Collections.ObservableDictionary`2.Remove(TKey key) in D:ProjetsCollectionsObservableDictionary.cs:line 152
         at Configuration.Snippets.RemoveSnippet(Snippet s) in D:ProjetsConfigurationSnippets.cs:line 64
         at TextExpander.Window1.btnRemoveSnippet_Click(Object sender, RoutedEventArgs e) in D:ProjetsMXG.Window1.xaml.cs:line 126
         at System.Windows.RoutedEventHandlerInfo.InvokeHandler(Object target, RoutedEventArgs routedEventArgs)
         at System.Windows.EventRoute.InvokeHandlersImpl(Object source, RoutedEventArgs args, Boolean reRaised)
         at System.Windows.UIElement.RaiseEventImpl(DependencyObject sender, RoutedEventArgs args)
         at System.Windows.UIElement.RaiseEvent(RoutedEventArgs e)
         at System.Windows.Controls.Primitives.ButtonBase.OnClick()
         at System.Windows.Controls.Button.OnClick()
         […]

    Do you have an idea of what is going on?

    Thank you,
    Martin

  15. Dr. WPF says:
    Hey Martin. Sorry for the late reply. This sounds like a bug worth investigating. Can you send me a repro?
  16. Andreas says:

    Hi Dr. WPF!

    I am having exactly the same problem as Martin. When removing an entry from the dictionary, I get the InvalidOperationException.

    Did you find a solution to this one already? Would be great!

    Thanks a lot!
    Andreas

  17. Dr. WPF says:

    Hi Andreas,

    Martin was kind enough to send me a stack trace, but I would still love to get a repro that I could actively debug. If you have something handy (and not too complicated ;-)), I’d love to get it and track this issue down.

    Thanks!
    -dw

  18. Andreas says:

    Hi again,

    unfortunately I cannot send you the code, and actually it is quite complicated as well. 🙂 But I just replaced the ObservableDictionary with the standard ObservableCollection from the .Net framework and it also throws an exception at exactly the same line of code. It seems like something is wrong in the binding because the entry is successfully removed from the collection, but it is not removed from the ListView. If I just continue the debugging after the exception, the entry is still in the ListView, and upon selection I get another exception because the entry is no longer available…

    It looks a little weird to me, but I will try to find the problem and post it here. If you or anyone has an idea, do not hesitate to post it here! At least the problem does not seem to be related to your ObservableDictionary.

    Andreas

  19. Dr. WPF says:

    Thanks for the follow up, Andreas. Sounds like a tough one, so best of luck. I would love to know the resolution when you figure it out. 🙂

  20. Andreas says:

    Hey,

    I think I figured it out… I had bound several CollectionViews to the same data source, and each view had another filter applied to it. Now, the exception was thrown when I removed an item from View1 which was not visible in View2 due to the filter. It seems like View2 tried to remove the item from the list although it was not even in there. Therefore the provided index was out of range because View2 displayed far less items than View1.

    Now I’m struggling with the next exception, but that does not seem to be related to the previous problem. 😉

    Andreas

  21. Igor says:

    G’day

    I am trying to bind an ObservableDictionary to a DataSource component (without any luck so far…)

    – Plan A: to inherit ObservableDictionary from BindingList<KeyValuePair<TKey,TValue>>;
    – Plan B: manually implement the following interffaces:
    IBindingList
    ICancelAddNew
    IRaiseItemChangeevents

    Any ideas?

  22. Dr. WPF says:

    Hi Igor,

    The ObservableDictionary class is designed specifically for WPF (or other frameworks that listen to INotifyCollectionChanged and INotifyPropertyChanged). If you wish to use it with other platforms (like WinForms), then yes, you will need to add the additional required interfaces. I probably would not try to derive from BindingList<T>, since that will require a pretty large rearchitecture.

    Cheers,
    -dw

  23. Nick says:

    Has anyone really solved this? I constantly am getting this if the dictionary is populated immediately on application start up. If it is populated later and modified nothing goes wrong and the UI and dictionary update as expected.

    Otherwise you get the error and the ListView or ListBox never updates again and the ObservableDictionary throws exceptions constantly in the background when an item in the dictionary has changed. This seems to happen on SetEntry when you have a new update and you remove the old value and populate the new. The exception seems to happen immediately after the NotificationCollectionChange event is fired.

    Any help is welcomed. 🙂

  24. Dr. WPF says:
    If you can give me a simple repro of this, Nick, I’d be happy to take a look. 🙂
  25. Nick says:

    Sent you a fully working example that breaks the dictionary.

  26. Nick says:

    BTW, if you are updating the Visual Element Via TCP WCF or some other transport.. then you will want to check the this.IsLoaded on your Window or Framework Element before you update the ObservableDictionary. I don’t know if this is a bug or something you should do for all ObservableCollections.
    Hope this helps.

  27. Dr. WPF says:

    Thanks so much for the repro, Nick! That was exactly what I needed.

    It turns out that I missed a couple of things in the change that I made for Paul back in April. This fully explains the problem that Martin reported (and probably others too).

    I have posted an updated sample that contains the simple 2-line fix. Please grab it and verify that it works for you.

    Wrt asynchronously accessing the collection, there are definitely some issues that you must address when accessing any observable collection. As long as the work is done on the same dispatcher that was used to create the collection, everything should be copacetic. You certainly shouldn’t see exceptions based on whether the elements have loaded. This would also be a good thing to test with the updated ObservableDictionary class.

    Thanks again for the repro! Someday I hope to have extra time to really optimize a few things in the dictionary, but at least the current version should be more solid now. 🙂

    Cheers,
    -dw

  28. Jim Foster says:

    I am checking out your class and I noticed a potential bug that VS 2008 SP1 points out. In ObservableDictionary.cs, method GetIndexAndEntryForKey, line 220. “The out parameter ‘entry’ must be assigned to before control leaves the current method”.

    While the compiler marks it as an error, it appears to be treating it as a warning and letting the compile and link finish.

    Normally, I would suggest that the output parameter be set to null, but since it is a struct and not a class, I am not sure what would be the best value.

    Thanks,
    Jim

  29. Dr. WPF says:

    Hi Jim,

    That’s not a compilation error… it’s the code editor being over dilligent with its intellisense errors. The compiler realizes that the out parameter is a struct and therefore has no real need of construction, but the code editor does not.

    I’ll try to remember to initialize it in the next update, just to avoid the confusion. 🙂

    Cheers,
    -dw

  30. John says:

    Hi,

    I’m working on a project and I was using ObservableColections and Dictionary until I found out this link, this ObservableDictionary makes life much easier, thank you.

    But(there is always a “but”),I tested the application that comes with the dictionary and it seems that if you delete or add more than one item the application crashes(System.InvalidOperationException in ValidateVersion()). There are any other updates to the class or what

  31. Dr. WPF says:

    Hi John,

    I cannot reproduce the problem you describe. I would need a simple repro to understand what is happening.

    Regards,
    -dw

  32. Mark Campion says:

    I’m not sure if this is working, or if its not meant to work in this way, but…

    I am trying to bind a DependencyProperty on a FrameworkElement, of type Person to an index within an ObservableCollection. So, if it is bound to element 1, whenever element 1 is replaced with a new Person object, the binding should fire and the DependencyProperty should be updated with the new Person.

    As I couldn’t use index’s within property paths in Silverlight, I switched the ObservableCollection to your ObservableDictionary, and simply keyed the entry on Person.PersonID. However, this is still not working. I see that in your example, you only bind to the whole collection not an index within the collection. Should this be possible using you ObservableDictionary?

  33. Dr. WPF says:

    Hi Mark,

    I’m afraid that scenario is not supported via WPF’s binding framework. You would need code logic to insert/replace the item at a specific index.

    Regards,
    -dw

  34. Daniel says:

    Hi dw,
    I don’t have the before and after to diff against for your 2-line fix. What did you do to fix this? I’m having a similar bug in some code I’ve written.

  35. Dr. WPF says:

    Hi Daniel,

    My fix was pretty specific to my class, as detailed below.

    Line 326 was:

        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, entry, index));

    became:

        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Add, new KeyValuePair<TKey, TValue>((TKey)entry.Key, (TValue)entry.Value), index));

    Line 338 was:

        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, entry, index));

    became:

        OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new KeyValuePair<TKey, TValue>((TKey)entry.Key, (TValue)entry.Value), index));

    Hope this helps!
    -dw

  36. Jim Foster says:

    Hello Doctor,

    I have a test program that I have bound three TextBoxes to three different dictionary keys. If I update the value in the text box, the dictionary get’s updated. If I programmaticly update the dictionary the text box does not get the updated value. My Mode is set to BindingMode.TwoWay.

    Is this something that should be doable with your dictionary?

    Thanks,
    Jim

  37. Yurik says:

    Property update is missing! When i bind to an individual item in wpf, a property item changed event is not fired. Need to add this line to the DoSetEntry() at the very end inside the if statement:

    OnPropertyChanged(“Item[]”);

    This is described very well in http://blogs.msdn.com/xtof/archive/2007/09/28/binding-to-indexers.aspx

  38. Dr. WPF says:

    Hi Jim,

    The two-way binding in your scenario will work if and only if the source object provides property change notifications. If your key values are objects that implement INotifyPropertyChanged, then it should work.

    Cheers,
    -dw

  39. Yurik says:

    Another thing: there is a significant number of extra unneeded code that becomes apparent if you use Resharper – subclasses do not need generic parameters – they can use their parent’s; many interfaces have already been declared as part of other interfaces, etc. I have been cleaning it up and can send you a copy – if you provide your email addr. (You can contact me at yuriastrakhan at gmail). One last thing – thanks to your code and resharper, I found a bug in the C# compiler: https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=388839

  40. Jim Foster says:

    Hi dw–Thanks for this great class…

    Hi Yurik–Thanks for that bug fix. That is EXACTLY what was missing. Personally, I think it should go in "FirePropertyChangedNotifications" outside the if statmentment. I put it there since an item can change without the Count changing and since this method gets called from other places. If an item is added or removed wouldn’t the Item[] also be updated???

    Should "OnPropertyChanged("Values");" be outside the if too?

    Thanks,
    Jim

  41. Dr. WPF says:

    Thanks for the suggested improvements, Yurik and Jim.

    There are actually lots of optimizations that could be made to this class, but I’ve not had the bandwidth to properly test such changes, and I continue to procrastinate there. 🙁 I took a lot of shortcuts (like editing an item by simply removing the old and adding the new) when I first put the class together.

    I’m happy to post any suggested improvements that have been tested. You can reach me at ask[at]drwpf.com. My response time depends entirely on my workload. 🙂

  42. Ken says:

    This is great. Well done!

  43. Chip says:

    I’d like to register to get the change events directly. The following code is what I am attempting, but the collectionChanged method is protected. What is the proper way to register interest?

    ObservableDictionary aDict = new ObservableDictionary();
    aDict.CollectionChanged += OnCollectionChanged;

    Thank for the great work!

    Chip

  44. Dr. WPF says:

    Hi Chip,

    You should be able to cast the dictionary to INotifyCollectionChanged to add the handler:

    (aDict as INotifyCollectionChanged).CollectionChanged += …

    Cheers,
    -dw

  45. Rafal says:

    hi Dr.WPF,

    wow since 2007 (when you wrote it) has now more than 2 years passed by and I can even now after so many years use your great class. I am trying to use your Observabledictionary under silverlight 3. MS didn’t make any improvements in this field since ver.2. I’ve noticed that the ISerializable and IDeserializable are not supported in SL. So your serialization part doesn’t work in SL.
    My question is. If I replace not working Ser/DeSer code with IXmlSerializable and methods like write-/readXML would it be enough?

    Thanks for your great work
    Rafal

  46. Dr. WPF says:

    Hi Rafal,

    My implementation of the ObservableDictionary class includes all of the interfaces implemented by the native Dictionary class in the full .NET framework. Silverlight uses a compact version of the .NET framework. The CoreCLR for Silverlight defines the Dictionary class as follows:

    public class Dictionary<TKey, TValue> : 
        IDictionary<TKey, TValue>, 
        ICollection<KeyValuePair<TKey, TValue>>,
        IEnumerable<KeyValuePair<TKey, TValue>>, 
        IDictionary, 
        ICollection, 
        IEnumerable

    Note that the serialization interfaces simply don’t exist in Silverlight’s CoreCLR. This means you can create an ObservableDictionary for Silverlight that is fully analogous to the native Dictionary class without supporting serialization.

    Of course, if you actually need to serialize the dictionary (for storage, remoting, etc), then I see no problem with using the XML serialization interfaces. 🙂

    Cheers,
    -dw

  47. SteveO says:

    Dr. WPF,

    Thanks for the class! Saved me a lot of time. One thing, I’m using it in VS 2010 B2 and get 3 CS0693 warnings. These look like BS warnings to me, but apperently Microsoft decided you can’t use the same names for inner template params as you do for the outer ones. The warnings are because you named all the collection params as TKey and TValue.

  48. Marc Messing says:

    Hi,

    thx for the great work.
    With VS 2010RC1 I got a Stackoverflow in Line 445. Replacing the Line with
    get { return ((IDictionary<TKey, TValue>)this)[(TKey)key]; }
    helped.

    Marc

  49. […] community has come up with a few implementations of an ObservableDictionary. This link is to one of the good ones, by Dr. WPF. Here is another ObservableDictionary on codeplex. Unfortunately, the first works only for […]

  50. Dr. WPF says:

    I’ve updated the dictionary to fix a couple of bugs:

    First, there’s the infinitely recursive call that Marc pointed out in his comment above. (Who writes this crap?)

    Second, I fixed the issue that Pete found with not raising the change notification for “Item[]” when a set occurs (see pingback comment above). This was actually a regression from an earlier fix. Doh! 😮 (Seriously, doesn’t anyone unit test these things!?)

    Big thanks to Pete and Marc! 😀