Silverlight学习笔记四:如何通过自定义ComboBox实现SelectedValue

一、发现问题。
继续学习SL,这次用到了ComboBox,自带的ComboBox可以通过ItemSource和DisplayMemberPath来实现Items的数据绑定,DisplayMemberPath类似于Asp.net控件中的DataTextField,但是奇怪的是,ComboBox并没有提供类似与DataValueField这样的属性,也就是说,在使用SelectedItem的使用,我们无法像过去一样,直接赋一个值就可以让它选择对应的Item,现在的SelectedItem必须是ItemSource里面的一个对象,这样使用起来会非常的麻烦,比如说,我们让ComboBox绑定到Suppliers集合,DisplayMemberPath为CompanyName,这个时候,如果我们想通过SupplierID来指定ComboBox的SelectedItem时,就必须到ItemSource中,按照SupplierID来找到对应的Supplier对象,再把这个Supplier赋给SelectedItem才行。
所以这里又要骂微软了,真的不知道他们是怎么想的,学习SL这段时间来,感觉他们在做SL的时候,想的太理想化,像个科研产品,不适合商用。很多常用的功能都给他们改的面目全非,把简单问题复杂化。

二、解决问题。
要解决这个问题,我们需要自己动手来写一个新的ComboBox,并给它添加上SelectedValuePath和SelectedValue这两个属性。
这里参考了Jones的SilverLight ComboBox,这篇文章,原文在这里http://www.engineserver.com/silverlightcombobox/
代码基本上和他的一样,但是修改了他代码中的部分问题,使其更加像Asp.net中的DropDownList。

我们新建了一个类,让它继承ComboBox,并且添加了SelectedValuePathProperty和SelectedValueProperty。这样,我们就可以通过Binding来和数据库进行绑定了,我在用Jones的代码时,界面出现之后,ComboBox并不会按照SelectedValuePath来显示指定的数据,但是在手工选择ComboBox里面的Item只有,它就能很好的工作了,这个很奇怪的问题花了我不少时间,结果发现,在SetBinding的时候,虽然我们让其Bind到SelectedValueProperty上,但是系统并没有通过SelectedValue的Set来赋值,所以SelectedValue的Set的代码并不会执行,这就导致初始化的时候,ComboBox并不按照Bind的显示数据。
后来,我在SelectedValuePropertyChanged中,对SelectedValue进行了赋值,使其可以正确工作。

ok,基本上就这么多了,其实整个功能很简单。下面看代码:
自定义ComboBox的代码:

 

ContractedBlock.gif ExpandedBlockStart.gif ComboBoxClassic
    public class ComboBoxClassic : ComboBox
    {
        
#region SelectedValuePathProperty
        
public static readonly DependencyProperty SelectedValuePathProperty = 
            DependencyProperty.Register(
"SelectedValuePath"typeof(string), 
            
typeof(ComboBoxClassic), null);
        
public string SelectedValuePath
        {
            
get
            {
                
return (string)GetValue(ComboBoxClassic.SelectedValuePathProperty);
            }
            
set
            {
                SetValue(ComboBoxClassic.SelectedValuePathProperty, value);
            }
        }
        
#endregion

        
#region SelectedValueProperty
        
public static DependencyProperty SelectedValueProperty = 
            DependencyProperty.Register(
"SelectedValue"typeof(object), typeof(ComboBoxClassic), 
            
new PropertyMetadata(new PropertyChangedCallback(SelectedValuePropertyChanged)));
        
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
                {
                    
throw new Exception();
                }
            }
        }
        
private static void SelectedValuePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d 
as ComboBoxClassic).SelectedValue = e.NewValue;
        }
        
#endregion

        
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));
                    var value 
= SelectedValue;
                }
                
catch
                {
                    
throw new Exception();
                }
            }
        }
    }

 

 

调用的方法:
我们假设编写一个修改数据的窗体,传入ProductID后,在界面上显示多个TextBox和ComboBox,ComboBox中显示Suppliers的信息,并和Product中的SupplierID绑定。

先通WCF获取Suppliers数据,并绑定到ItemSource上。同时设置了DisplayMemberPath和SelectedValuePath属性。

 

        void client_getAllSuppliersCompleted(object sender, getAllSuppliersCompletedEventArgs e)
        {
            cb.ItemsSource 
= e.Result;
            cb.DisplayMemberPath 
= "CompanyName";
            cb.SelectedValuePath 
= "SupplierID";
        }

 

使用时,先获取Product信息,再绑定

 

void client_getProductCompleted(object sender, getProductCompletedEventArgs e)
        {
            products 
= e.Result;
            
//设置ComboBox所在的Grid的DataContext。
            content.DataContext = products;
            
//设置Bind信息,让其和Product的SupplierID绑定。
            
//使用TwoWay,这样ComboBox在SelectedItem变动之后,会自动更新Product的SupplierID。
            System.Windows.Data.Binding bind = new System.Windows.Data.Binding("SupplierID");
            bind.Mode 
= System.Windows.Data.BindingMode.TwoWay;
            cb.SetBinding(ComboBoxClassic.SelectedValueProperty, bind);
        }

 

 

转载于:https://www.cnblogs.com/libra163/archive/2009/01/06/1370146.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值