|
|
|
|
Can I bind my ItemsControl to a dictionary?
|
 |
|
Location: Blogs Ask Dr. WPF |
 |
| Posted by: Dr. WPF |
9/16/2007 10:47 PM |
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. J)

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
|
|
| Permalink |
Trackback |
Comments (41)
Add Comment
|
bug fix |
By Nathan on
11/23/2007 9:35 PM |
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); } }
|
|
|
Re: bug fix |
By Dr. WPF on
12/17/2007 11:00 AM |
| Great catch, Nathan! I have added the fix to the sample. Much thanks! -dw |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By marco.ragogna on
1/21/2008 3:18 AM |
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 |
|
|
Problem sorting ObservableSortedDictionary |
By Rodrigo on
2/11/2008 12:08 AM |
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 |
|
|
Problem sorting ObservableSortedDictionary |
By Dr. WPF on
2/11/2008 12:17 AM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By marco.ragogna on
2/21/2008 6:33 AM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Dr. WPF on
2/21/2008 11:09 AM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By marco.ragogna on
2/22/2008 12:34 AM |
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. |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Paul on
4/11/2008 5:43 AM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Dr. WPF on
4/11/2008 11:44 AM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Dr. WPF on
4/28/2008 3:48 PM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Nicole Taylor on
5/29/2008 6:14 AM |
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); |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Dr. WPF on
5/30/2008 9:01 AM |
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. |
|
|
Re: Can I bind my ItemsControl to a dictionary? - TreeView and Remove |
By Martin on
6/30/2008 1:46 PM |
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:\Projets\Collections\ObservableDictionary.cs:line 199 at Collections.ObservableDictionary`2.FireEntryRemovedNotifications(DictionaryEntry entry, Int32 index) in D:\Projets\Collections\ObservableDictionary.cs:line 311 at Collections.ObservableDictionary`2.DoRemoveEntry(TKey key) in D:\Projets\Collections\ObservableDictionary.cs:line 267 at Collections.ObservableDictionary`2.Remove(TKey key) in D:\Projets\Collections\ObservableDictionary.cs:line 152 at Configuration.Snippets.RemoveSnippet(Snippet s) in D:\Projets\Configuration\Snippets.cs:line 64 at TextExpander.Window1.btnRemoveSnippet_Click(Object sender, RoutedEventArgs e) in D:\Projets\MXG.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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Dr. WPF on
6/30/2008 1:47 PM |
Hey Martin. Sorry for the late reply. This sounds like a bug worth investigating. Can you send me a repro? |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Andreas on
7/22/2008 4:26 AM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Dr. WPF on
7/22/2008 12:35 PM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Andreas on
7/22/2008 11:35 PM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Dr. WPF on
7/23/2008 1:41 AM |
| 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. :) |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Andreas on
7/23/2008 11:29 PM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Igor on
8/5/2008 11:37 AM |
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? |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Dr. WPF on
8/5/2008 11:43 AM |
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 |
|
|
Added item does not appear at given index |
By Nick on
8/13/2008 2:27 PM |
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. :) |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Dr. WPF on
8/13/2008 2:54 PM |
If you can give me a simple repro of this, Nick, I'd be happy to take a look. :) |
|
|
Added item does not appear at given index |
By Nick on
8/14/2008 9:01 PM |
| Sent you a fully working example that breaks the dictionary. |
|
|
Re: Added item does not appear at given index |
By Nick on
8/14/2008 9:04 PM |
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. |
|
|
FIXED! Added item does not appear at given index |
By Dr. WPF on
8/14/2008 9:16 PM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Jim Foster on
11/7/2008 2:47 PM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Dr. WPF on
11/16/2008 3:57 PM |
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 |
|
|
Bugs or do I miss something? |
By John on
11/17/2008 8:50 AM |
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’s posted is the most up to date version? In my dictionary I took out my ObservableColections and replace them with ObservableDictionary, assigning to each of the elements that were using ObservableColections the new specific ObservableDictionary values collection. Everything was fine so far, but when I tried to delete something or clear the dictionary nothing happened to the elements content, they had the same content, although the dictionary has change its content. The elements that I’m using, ListBox and XamDataGrid are listen to INotifyCollectionChanged and INotifyPropertyChanged events, so (if the above details make any sense) does anyone has any idea what I’m missing?
Any help is much appreciated. |
|
|
Re: Bugs or do I miss something |
By Dr. WPF on
11/30/2008 7:30 AM |
Hi John,
I cannot reproduce the problem you describe. I would need a simple repro to understand what is happening.
Regards, -dw |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Mark Campion on
12/1/2008 7:30 AM |
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? |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Dr. WPF on
12/9/2008 4:33 PM |
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 |
|
|
Re: FIXED! Added item does not appear at given index |
By Daniel on
12/12/2008 3:38 PM |
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. |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Dr. WPF on
12/17/2008 3:40 PM |
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 |
|
|
Can I bind my TextBoxes to your dictionary? |
By Jim Foster on
12/18/2008 8:09 AM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Dr. WPF on
12/20/2008 12:05 AM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Yurik on
12/19/2008 12:27 PM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Yurik on
12/22/2008 7:10 AM |
| 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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Jim Foster on
12/22/2008 8:44 AM |
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 |
|
|
Re: Can I bind my ItemsControl to a dictionary? |
By Dr. WPF on
1/7/2009 3:12 PM |
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. :) |
|
|
|
 |
|