Given a dictionary of <string, Drink>, how would you bind the dictionary.Values to a WPF ListBox, so that the items use the .Name property?
struct Drink
{
public string Name { get; private set; }
public int Popularity { get; private set; }
public Drink ( string name, int popularity )
: this ( )
{
this.Name = name;
this.Popularity = popularity;
}
}
Setting the
ItemsSourceon an items control creates a binding to the enumerator for the source object. The enumerator of aDictionary<T1, T2>is of typeIEnumerable<KeyValuePair<T1, T2>>. So in your item template, you can bind to theKeyandValueproperties, and use the path syntax to get specific properties of the key and value.Here’s an example. First the code that creates and populates the dictionary and adds it to the resource dictionary (there are lots of different ways you can expose the dictionary to data binding; this one’s simple):
Now the XAML for populating a
ListBox(though aListViewwould be easier, because you wouldn’t have to define a template this complicated to make it look nice):The XAML for a
ListViewis a lot simpler, and displays more nicely to boot:To answer your follow-up questions:
I recommend Adam Nathan’s Windows Presentation Foundation Unleashed. The chapter on layout with panels explains how the Grid works in considerable detail. The
Grid‘s pretty counter-intuitive in a lot of ways. You think that you’d want to create a singleGridthat contains many items, but the number of rows and columns in aGridisn’t dynamic. So what you do instead is create aGridfor each item, and then use the shared-size functionality to make sure that the columns in eachGridare the same size. TheListViewhas quirks of its own, but it’s a lot more straightforward for the common “display multiple items in a grid” use case.DynamicResourceis a markup extension that works a lot likeStaticResource. The difference is that when the XAML parser resolvesStaticResourceas it parses it – if the referenced resource isn’t in the resource dictionary, it throws an exception.DynamicResourceresolves the reference if the item gets added to the dictionary later. There’s a bit of a performance cost to this, but it’s negligible in most cases. The code I posted works if you useStaticResource, because the XAML gets parsed inInitializeComponent. But I don’t like having to remember that, so I useDynamicResourceby default if I’m binding to something that I’m adding to the resource dictionary in code and just don’t worry about whether it’s being created before or after the XAML gets parsed.And as for the toolbox: Maybe I’ll start using that in VS2010, but I find the one in 2008 unusably buggy. And not very useful anyway. I do almost all of my layout work in the editor, and some in Kaxaml. I think the visual editor in 2008 actually made learning WPF harder, because it imposed an abstraction layer between me and the XAML (which is itself an abstraction layer between me and the WPF object model). And it’s not a very good abstraction layer: the design decisions that went into deciding what should be hidden and what should be visible aren’t, it seems to me, the right ones. Also it’s buggy as hell.