Implementing SelectedValue with the Silverlight ComboBox

Here’s the scenario … You have a Customers collection and an Orders collection.  In the Orders collection, an Order has a CustomerID property; this is the key to an item in the Customers collection.  Your goal is a ComboBox that updates the CustomerID property of a Customer, but interacts with the end user in terms of customer names.  If that doesn’t make sense, code & pictures help …


Here’s how you can accomplish this in markup in WPF (the l:Collection here is just a Collection<object>):





        <l:Collection x:Key=”Customers”> <!– Collection<object> –>

            <l:Customer ID=”1″ CustomerName=”Wilma” />

            <l:Customer ID=”2″ CustomerName=”Betty” />

            <l:Customer ID=”3″ CustomerName=”Fred” />

            <l:Customer ID=”4″ CustomerName=”Barney” />



        <l:Collection x:Key=”Orders”> <!– Collection<object> –>

            <l:Order Description=”Magic carpet” CustomerID=”1″ />

            <l:Order Description=”Blue suede shoes” CustomerID=”4″ />

            <l:Order Description=”Hanna Montana wig” CustomerID=”1″ />







        <!– Show a customer ID –>

        <StackPanel Orientation=”Horizontal”>

            <TextBlock Text=”Customer ID:” Margin=”5″/>

            <TextBlock Name=”TextBlock1″ Margin=”5″  Text=”1″/>



        <!– Pick the customer ID that will be shown above –>

        <ComboBox ItemsSource=”{StaticResource Customers}”


                  SelectedValue=”{Binding Text, ElementName=TextBlock1}”

                  DisplayMemberPath=”CustomerName” />







More on that ComboBox after these pictures,


Initially we get this:



… and here I am opening the ComboBox, and changing the customer to Betty (her CustomerID is 2):



So that changed the “Customer ID” from 1 to 2, but I (the end user) interacted only with customer names via the ComboBox.


Now let’s analyze that ComboBox markup:


<ComboBox ItemsSource=”{StaticResource Customers}”


          SelectedValue=”{Binding Text, ElementName=TextBlock1}”

          DisplayMemberPath=”CustomerName” />


The ItemsSource is set to the Customers list.  So when you open the ComboBox, you’ll see customers.  Specifically, for each customer in that list, you’ll see the Customer.CustomerName, because the DisplayMemberPath is set to the “CustomerName” property.


Now whatever is selected in the ComboBox, I want it to show up in TextBlock1.  If I just bind SelectedItem to TextBlock1, I’d be sending the whole Customer object over, but really I just want the TextBlock.Text to show the Customer.CustomerID.  So, instead of binding SelectedItem to the TextBlock, I bind SelectedValue.  SelectedValue behaves the same as SelectedItem, though, until you set a SelectedValuePath.  When you set SelectedValuePath, then SelectedValue becomes that path into the SelectedItem.  For example, if your SelectedItem is a Customer, and your SelectedValuePath is “ID”, then SelectedValue is going to be Customer.ID, which is just what we want.


(Note in this example I defaulted TextBlock1.Text to ‘1’.  Otherwise the SelectedValue binding gets confused.  Alternatively, I could have set the Binding.Mode to ‘OneWayToSource’.)



Next let’s do this with the Silverlight ComboBox, because it doesn’t have the SelectedValue or SelectedValuePath properties.  But we can still get it to work with a little bit of code. 


Update: The Silverlight 4 Beta does now have SelectedValue and SelectedValuePath properties.


Change the markup to this:


<ComboBox ItemsSource=”{StaticResource Customers}”


          SelectionChanged=”ComboBox_SelectionChanged” />


… and write a little code:


private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)


    var comboBox = sender as ComboBox;

    TextBlock1.Text = (comboBox.SelectedItem as Customer).ID.ToString();





It’d be nice if we could do this all in markup, though, and in fact there have been some posts on the Silverlight forums to do just that with a Binding value converter.  Also, I wish I could have this feature on a TextBlock too, not just on ComboBox.  So below is a handy value converter that can be used with a Binding.  (I created this on the Silverlight 3 beta, but most of this is applicable to Silverlight 2 as well.)  The idea of this is to mimic the ComboBox mechanism.  First, here’s an example of the converter being created:



    <l:Collection x:Key=”Customers”> <!– Collection<object> –>




    <l:Collection x:Key=”Orders”> <!– Collection<object> –>




    <l:ValueToItemConverter x:Key=”CustomerID2Name”

                            ItemsSource=”{StaticResource Customers}”


                            DisplayMemberPath=”CustomerName” />



… notice that it looks much like the ComboBox.  The only thing it doesn’t have is a counterpart to the SelectedValue property, because the value is what comes into the IValueConverter methods.  Now let’s use it in a trivial master/detail:


<Grid >






    <!– List of Orders –>

    <ListBox ItemsSource=”{StaticResource Orders}” Name=”ListBox1″>



                <TextBlock Text=”{Binding Description}” />





    <!– Detail for the selected Order –>

    <StackPanel Grid.Column=”1″

                DataContext=”{Binding SelectedItem, ElementName=ListBox1}”>

        <TextBlock Text=”{Binding Description}” />


        <!– Order.CustomerID convertered to a Customer.CustomerName –>

        <TextBlock Text=”{Binding CustomerID,

                                  Converter={StaticResource CustomerID2Name}}” />




… which gives us this (here I’ve selected the first order):


The key here is that in the detail, rather than showing CustomerID 1 from the Order, we see “Wilma”.



And finally, here’s an example using this value converter in the column of a DataGrid.  Again, the items are Orders, and the column shows a CustomerID as a CustomerName, using a TextBlock when the cell isn’t being edited, and as a ComboBox when it is. 


First, create a version of the value converter that doesn’t have DisplayMemberPath set (because ComboBox has its own DisplayMemberPath property):


<l:ValueToItemConverter x:Key=”CustomerID2Customer”

                        ItemsSource=”{StaticResource Customers}”

                        ValuePath=”ID” />


… and then the DataGrid itself:


<d:DataGrid AutoGenerateColumns=”False”

            ItemsSource=”{StaticResource Orders}”>


        <d:DataGridTextColumn Binding=”{Binding Description}” />






                    <TextBlock Text=”{Binding CustomerID,

                                              Converter={StaticResource CustomerID2Name}}”









                         ItemsSource=”{StaticResource Customers}”

                         SelectedItem=”{Binding CustomerID, Mode=TwoWay,

                                          Converter={StaticResource CustomerID2Customer}}” />








Comments (10)

  1. &#160; …and Why Coding Is So Much Fun A Gonzo Adventure In What You Can Learn When You’re Not Doing What

  2. johnzabroski says:

    This is just plain nasty, but perhaps there are reasons for the nastiness you are skipping over?

    More likely, I think, you need to step back and reconsider the theoretical requirements – figure out what it is you want to say rather than how to say it.

    I don’t know where to begin.  Why an untyped collection – Collection<Object>?

    @It’d be nice if we could do this all in markup, though

    No!  I think you are missing the point here.  The key is that we want to do things DECLARATIVELY.  A key aspect of declarative programming is separation of concerns.  We shouldn’t have to manually shovel data around – this is 2009.  "Pointer swizzling" like you are doing here just doesn’t cut it.  It is not decoupled, and it makes me write a lot of error prone code.

  3. brauliod says:

    Mike… Thanks for the sample, unfortunately Combobox on Silverlight it’s a buggy and uncomplete control… so we have no other chance than going the coding way to achieve tasks.

    A pity not being able to implement this in a clean declarative way, but I rather preffer coding than having to perform 4 nasty declarative tricks to get somethings that you don’t know whether it will work fine or not.

  4. markwalker says:

    Can you show the source of the ValueToItemConverter class?


  5. I attached a project with the sample code, including the value converter.

    Thanx, Mike

  6. brauliod says:

    This approach as well, it’s a good one (custom combo extension…)

  7. PeteF says:

    Mike – do you have a ValueToItemConvertor that would work for an Item Source of type DomainDataSource instaed of IEnumerable