Ah, WPF. You’ve dotted your tees and crossed your eyes and your data bound control is still not showing any data from your collection. You set a breakpoint in the property getter that is providing the collection data, the breakpoint gets hit and returns your data, but the data doesn’t appear at the other end of the binding pipeline, in the databound control. You check the Output debug window in VS to see what data binding error messages might be found there, but there are none. What’s going on?
The problem is that the data collection you’re returning doesn’t meet WPF’s data binding requirements, so WPF ignores the binding expression and goes on its merry way. I can understand why WPF doesn’t throw an exception for this situation, but could we at least get an error message logged to the Output window like other data binding errors?
For collection properties to work on WPF controls in XAML markup, XAML requires that the collection object instance implement the IList interface. That means the data collection you’re binding to that property needs to implement IList also.
If your data collection is an IEnumerable, such as data returned by a yield return iterator, your control will display no data at runtime and you’ll see no error messages.
If your data collection implements IList<T>, your control will display no data at runtime and you’ll see no error messages. A class that implements IList<T> does not automatically support IList.
If your data collection is a Dictionary<K,V>, you can data bind to the dictionary’s Values collection property, which implements IList<T>. You can probably guess where this is going… The dictionary’s values collection type implements IList<T>, but not IList. Your control will display no data at runtime and you’ll see no error messages.
Note that the type of the property that is providing the data collection is more or less immaterial. What matters is whether the object that property returns implements IList. WPF/XAML will query at runtime for the IList interface on whatever object is returned by the data bound source property.
List<T>, Collection<T>, and ObservableCollection<T> all implement IList, so if you’re using these as your underlying storage class you’re good to go. If your underlying storage is anything else, you probably have some work to do.
In the Dictionary<K,V>.Values case, one simple solution is to return Values.ToList(). The List object returned implements IList so you’re good to go.
Before putting that code to bed, though, give some thought to the performance implications: ToList() will create a new list of references to all the data in the dictionary Values collection, and it will do that every time anything fetches the property value. The memory consumption is proportional to the number of items in the dictionary, but not to the size of those objects. The objects in the dictionary are not copied, the list just contains references to the objects (as does the dictionary).
For a small collection of a few hundred entries or less, this is probably no big deal. For a large collection with tens of thousands of items or more, creating a new list of N object references every time the property is fetched is probably not a good idea.