“How do you bind a ComboBox to a collection of objects, and then bind a property from the selected object’s to some other scalar property?” I received this question today from a friend of mine (a variation of this question). I decided to walk through the scenario here in case anyone else runs into it. This is one of those things that can be confusing … it is simple, but it is is much easier shown the explained. This post lays out the scenario using some new features to Silverlight 4 and you can download the sample code at the end.

When we first load the page and open the ComboBox it should look like this, with each state’s full name (State.Name) being displayed in the ComboBox items.

image

And when we select a state it’s state code (State.Code) is bound to the TextBlock. In the screen capture below you can see the state of Washington is selected and its state code of WA is bound to the TextBlock above the ComboBox.

image

This quick demo shows the behavior we want to achieve. Let’s assume we have an object (we’ll assume it is a ViewModel) bound to the Silverlight View (the View being the UserControl).

NOTE: You’ll notice I am using View and ViewModel here and you’ll probably conclude I am using MVVM … and you would be correct. However keep in mind that MVVM is not needed, I just decided to use it to make the example clearer using separation with classes. We could have called them whatever we wanted.

This ViewModel has a property called States which is a ObservableCollection<State>. The State object the properties:

  • string Code (ex: WA)
  • string Name (ex: Washington)

The ViewModel is bound to the View, as its DataContext. A ComboBox in the View is bound to the list of states in the ViewModel’s States property. When the project loads, we expect the list of states to be displayed in the ComboBox.Each state’s full name should appear (from the State.Name property). When a state is selected in the ComboBox, the State.Code property should be grabbed and set to the ViewModel’s SelectedStateCode property. The trick to doing this is to set your XAML for your ComboBox like this:

   1: <ComboBox Height="23" HorizontalAlignment="Left" Margin="12,50,0,0" 
   2:           Name="comboBox1" VerticalAlignment="Top" Width="252" 
   3:           ItemsSource="{Binding Path=States, Mode=OneWay}" 
   4:           SelectedValue="{Binding Path=SelectedStateCode, Mode=TwoWay}" 
   5:           DisplayMemberPath="Name" 
   6:           SelectedValuePath="Code"  />
   7: <TextBlock Height="23" HorizontalAlignment="Left" 
   8:            Margin="187,16,0,0" Name="textBlock1" 
   9:            Text="{Binding Path=SelectedStateCode}" 
  10:            VerticalAlignment="Top" Width="65" />

Notice the following 4 properties are set as follows:

  • ItemsSource is bound to the ViewModel’s States property (a collection of State objects)
  • DisplayMemberPath is set to “Name” (This is the State.Name property)
  • SelectedValuePath is set to “Code” (This is the State.Code property)
  • SelectedValue is bound to the ViewModel’s SelectedStateCode property

The key here are the DisplayMemberPath and SelectedValuePath properties. These apply to the object that each item in the ComboBox is bound to. In other words, these properties are set to the State, not the ObservableCollection<State>. Also, notice these properties are not data bound, they are instead set to the name of the properties respectively. We do not want the values of the properties here, we want the actual name of the properties (which is why it is called DisplayMemberPath and SelectedValuePath).

image

 

 

Download the source code for this sample ComboBox project here.

 

WhitePaper2

 

SelectedValue and SelectedValuePath are new to Silverlight 4. You can find more information on this new feature to Silverlight 4 and many more in the Silverlight 4 whitepaper found here.

 

 

I hope this helps!

UPDATE: I added the XAML for the TextBlock above too. The compelte code can be downloaded from the link above.