Display Members Value Members and LookUp Bindings

If you want to show only one of the properties, the ListBox class (and the rest of the ItemsControl-derived controls—e.g., Menu, ListBox, ListView, ComboBox, TreeView, etc.) provides the DisplayMemberPath property:

<ListBox ... ItemsSource="{Binding}" DisplayMemberPath="Name" /> This at least gives us part of the data, as you can see in Figure 7-5.

10 ListBinding

Torn John Melissa

Name: Tom

Age: 11

[ Birthday ] [ < | [ > ] [ Add ] ( Sort | | Filter | [ Group

Figure 7-5. The DisplayMemberPath in action

In addition to the path describing the data to display, the ItemsControl class provides a path to describe the selected value of a piece of data:

<ListBox ... Name="lb" ItemsSource="{Binding}" DisplayMemberPath="Name" SelectedValuePath="Age" />

The SelectedValue is exposed from the ItemsControl as an application-defined way to separate the data from what's displayed. By default, the SelectedValue, the SelectedItem, and the object used to construct the item at that spot in the list are all the same (e.g., a Person if we hadn't changed it by setting the SelectedValuePath). This data is often used when the selection changes or an item is double-clicked:

void lb_MouseDoubleClick(object sender, MouseButtonEventArgs e) { int index = lb.Selectedlndex;

Person item = (Person)lb.Selectedltem; int value = (int)lb.SelectedValue; // Age

// Do something profitable with this data } ...

The difference between display value and selected value becomes especially interesting when you want to do something like a combo box with friendly names (e.g., salesperson name), but key off of opaque values in the real data (e.g., salesperson ID).

For example, if we wanted to provide a UI that mapped ages represented in scary numbers to soothing phrases, we could construct a NamedAge type for use in populating a look-up table, as shown in Example 7-7.

Example 7-7. A helper for populating a look-up table public class NamedAge : INotifyPropertyChanged { // INotifyPropertyChangeIdINotifyPropertyChanged Members public event PropertyChangedEventHandler PropertyChanged; protected void Notify(string propNameForAge) { if( this.PropertyChanged != null ) { PropertyChanged(this, new PropertyChangedEventArgs(propNameForAge));

string nameForAge;

public string NameForAge {

get { return this.nameForAge; } set {

if( this.nameForAge == value ) { return; } this.nameForAge = value; Notify("NameForAge");

int ageId; public int AgeId {

if( this.ageId == value ) { return; } this.ageId = value; Notify("AgeId");

Example 7-7. A helper for populating a look-up table (continued) }

class NamedAges : ObservableCollection<NamedAge> { }

Now we can populate the table for looking up an age's name from its number, as in Example 7-8.

Example 7-8. A look-up table suitable for binding

<local:NamedAges x:Key="NamedAgeLookup"> <local:NamedAge NameForAge="zero" AgeId="0" /> <local:NamedAge NameForAge="one" AgeId="l" />

</local:NamedAges>

This handy table is all we need to replace the TextBox for entering hard-to-format-correctly ages into an easy-to-use combo box with all of the values filled in for us, as shown in Figure 7-6.

Figure 7-6. Data binding to a look-up table

OK, obviously this particular example isn't useful, but mapping IDs to names is something we want to do all the time in data binding applications. To get our combo box to show the list of available options, we need to bind the set of options to our look-up table, setting the display and value members appropriately, as in Example 7-9.

Example 7-9. Data binding to a look-up table <ComboBox ...

ItemsSource="{Binding Source={StaticResource NamedAgeLookup}}" DisplayMemberPath="NameForAge" SelectedValuePath="AgeId" />

Example 7-9 tells the combo box where the possible choices come from (the NamedAgeLookup table), which property to show the user (the NameForAge property), and which property is the real value (the AgeId property). The final step is the bit of binding that tells the combo box where to get the currently selected value (in terms that match our selected value path; in other words, Age), as in Example 7-10.

Example 7-10. Binding the look-up table to the selected value <ComboBox ...

ItemsSource="{Binding Source={StaticResource NamedAgeLookup}}" DisplayMemberPath="NameForAge" SelectedValuePath="AgeId" SelectedValue="{Binding Path=Age}" />

Just as before, where the TextBox object's Text property was set to bind to the Age property of the currently selected Person, so is the ComboBox object's SelectedValue property set. As the display value changes (due to interaction with the user), the selected value is updated, as is the underlying Age. Likewise, as the Age changes (like when the Birthday button is clicked), the binding synchronizes the selected value, causing the value displayed in the combo box to change.

All of this is very handy, but in our case, we don't really want to have named ages, nor do we want to display a single property in the ListBox for each Person object it displays.

Was this article helpful?

0 0
Project Management Made Easy

Project Management Made Easy

What you need to know about… Project Management Made Easy! Project management consists of more than just a large building project and can encompass small projects as well. No matter what the size of your project, you need to have some sort of project management. How you manage your project has everything to do with its outcome.

Get My Free Ebook


Post a comment