If you are like me, you were surprised that Silverlight does not have a SelectedValuePath and a SelectedValue property for Combo Boxes and List Boxes.  I became frustrated with working around the absence of those properties.  Some people feel that they are not needed since we can simply add a business object to the control as an item.  The problem with that is data binding.  I use business objects/classes as items in the list but whenever an item is selected by the user or whenever a value is read in from a database, data binding cannot be used to automatically determine or set the value the control because there is no SelectedValue property.

Example of the problem:
 

AssignmentTypes assgnTypes  = new AssignmentTypes( );
combo.ItemsSource = assgnTypes;
combo.DisplayMemberPath = "AssignmentType";
//problem nothing to set the value for selected item automatically

combo.DataContext = myDBTable;
System.Windows.Data.
Binding comboBinding = new System.Windows.Data.Binding( "AssignmentTypeID" );
comboBinding.Mode = System.Windows.Data.
BindingMode.TwoWay;
combo.SetBinding(
ComboBox
.DisplayMemberPathProperty, comboBinding );    //THIS IS NO GOOD TO ME BECAUSE THE DISPLAY VALUE IS A STRING AND THE DB HAS AN INTEGER VALUE

public class AssignmentTypes : List<AssignmentTypes.AssignmentTypeItem>
{
            //get types from db...
            //add items...

public class AssignmentTypeItem
{

private int _AssignmentTypeID;
public int AssignmentTypeID
{
   
get { return _AssignmentTypeID; }
   
set { _AssignmentTypeID = value; }
}
private string _AssignmentType;
public string AssignmentType
{
   
get { return _AssignmentType; }
    set
{ _AssignmentType = value; }
}
public override string ToString()
{
   
return AssignmentType;
}

}
}

As you can see from the code above, the display value can be databound to my data object but that is no good.  I need the AssignmentTypeID to be the value passed to my data object, not the display item.  So here's what I did to solve the problem:

Solution:
I created an extended ComboBox that gives me the SelectedValuePath and SelectedValue properties.

using System;
using
System.Net;
using
System.Windows;
using
System.Windows.Controls;
using
System.Windows.Documents;
using
System.Windows.Ink;
using
System.Windows.Input;
using
System.Windows.Media;
using
System.Windows.Media.Animation;
using
System.Windows.Shapes;
using
System.Linq;
 

namespace EnhancedControls
{
    public class ComboBoxClassic :
ComboBox

{
   
public static readonly DependencyProperty SelectedValuePathProperty = DependencyProperty.Register( "SelectedValuePath", typeof( string ), typeof( ComboBoxClassic ), new                     PropertyMetadata( new PropertyChangedCallback( SelectedValuePathPropertyChanged ) ) );

    public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.Register( "SelectedValue", typeof( object ), typeof( ComboBoxClassic ), null);

    public ComboBoxClassic()
    :
base()
    {

        base
.SelectionChanged += new SelectionChangedEventHandler( ComboBoxClassic_SelectionChanged );
    }
   
void ComboBoxClassic_SelectionChanged( object sender, SelectionChangedEventArgs e )
    {
       
if ( SelectedItem != null && !string.IsNullOrEmpty( SelectedValuePath ) )
        {
            try
            {
                SetValue(
ComboBoxClassic.SelectedValueProperty, SelectedItem.GetType().GetProperty( SelectedValuePath ).GetValue( SelectedItem, null ) );
            }
           
catch
            {
                //Add exception handling

            }
        }
    }
   
static void SelectedValuePathPropertyChanged(DependencyObject d,DependencyPropertyChangedEventArgs e)
    {
    }
   
public string SelectedValuePath
    {
       
get { return ( string )GetValue( ComboBoxClassic.SelectedValuePathProperty ); }
       
set { SetValue( ComboBoxClassic.SelectedValuePathProperty, value ); }
    }
   
public object SelectedValue
    {
       
get
        {
           
return GetValue( SelectedValueProperty );
        }
       
set
        {
           
try
            {
               
var q = ( from item in Items
               
where item.GetType().GetProperty( SelectedValuePath ).GetValue(item,null).Equals( value )
               
select item ).Single();
                SelectedItem = q;
            }
           
catch

            { }
       }
    }

        }

}

 

Now with the extended ComboBox control I can do what I needed:
AssignmentTypes assgnTypes  = new AssignmentTypes( );
combo.ItemsSource = assgnTypes;
combo.DisplayMemberPath = "AssignmentType";
combo.SelectedValuePath = "AssignmentTypeID";

combo.DataContext = myDBTable;
System.Windows.Data.
Binding comboBinding = new System.Windows.Data.Binding( "AssignmentTypeID" );
comboBinding.Mode = System.Windows.Data.
BindingMode.TwoWay;
combo.SetBinding(
ComboBoxClassic
.SelectedValuePathProperty, comboBinding );    //THIS IS GOOD TO ME

Everything now works great using the extended ComboBox.  The database gets the value it needs and the user only sees the friendly display string automatically.  I can now use this in my normal processing of databinding without have to manually do things in SelectionChanged events.  Why this was left out of Silverlight is beyond me unless I was missing some other way around this.

 

Hope it helps,
Jones