SetBinding ComboBox Silverlight (网摘)

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  = newAssignmentTypes( );
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"typeofstring ), typeofComboBoxClassic ), new                     PropertyMetadatanew PropertyChangedCallback( SelectedValuePathPropertyChanged ) ) );
    
public static readonly DependencyProperty SelectedValueProperty = DependencyProperty.Register( "SelectedValue"typeofobject ), typeofComboBoxClassic ), 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
posted @ 2010-08-03 10:13  jiangC  阅读(175)  评论(0编辑  收藏  举报