现在的位置: 首页 > 综合 > 正文

绑定到Collection与绑定到CollectionViewSource的不同及解决方案

2013年01月22日 ⁄ 综合 ⁄ 共 1882字 ⁄ 字号 评论关闭

WPF中,所有的ItemsControl都可以将ItemsSource绑定到后台的数据源上。一般情况下,会将这个ItemsSource直接绑定到一个ObservableCollection上。

比如我们要做一个旅游线路选择的界面。有两个ComboBox用来选择旅游的出发地和目的地。假设Province类中有一个静态的列表包含了中国所有的省份名称。一般就会把这两个ComboBoxItemsSource属性直接绑定到这个省份列表上。

但是这样做有一个问题。虽然每个ComboBox都有自己的Items.Filter属性用于Item过滤。但是由于绑定到了同一个Collection上,给其中任意一个ComboBox设置Filter就相当于同时给所有的ComboBox设置了Filter。这可不是我们想要的行为。

产生这个行为的原因是,ItemsControl在绑定到Collection上时,会先去获取这个CollectionICollectionView。由于是同一个Collection,所以不同的ComboBox绑定到同一个Collection上时,获取到的也是同一个ICollectionView。而ComboBoxFilter属性也就是这个ICollectionViewFilter。不单单Filter是这样,与View相同的Sort之类也是这样的。

但是我们的确就是要不同的ItemsControl绑定到同一个Collection上,但是又分别地控制View。不能从Collection上做手脚,就在View上做手脚。我们可以让ComboBox绑定到不同的View上。这些View共享同一个Collection不就行了?代码如下。

 

   <CollectionViewSource x:Key="ProvinceSource" x:Shared="False"

                        Source="{x:Static m:Province.Provinces}" />

 

然后使用如下的代码绑定到ComboBoxItemsSource上。

 

      <ComboBox ItemsSource="{Binding Source={StaticResource ProvinceSource}}"/>

 

其中起作用的就是ViewSource上面设置的x:Shared属性。有了这个属性,不同的控件实际绑定到的就是不同的View了。

 

但是在使用这个方法的时候发现了一个问题。就是这个方式与直接绑定到Collection上是不同的。

直接绑定到数据源上,ComboBox显示出来的时候是没有选择任何一项的。

但是绑定到ViewSource上,CombBox一显示出来,默认会选择第一项。(网上已经有人抱怨这个问题了

 

如果仅仅是显示上有些不同也就算了。但是,默认选择第一项,CombBox就会去更新SelectedItem所绑定到的后台数据。这样后台原有的数据就被清掉了。这个是不可容忍的。

 

解决方案倒是有的。

1.       使用一个Converter,在Convert函数中把这个ViewCurrentPosition设置为-1就可以了。不过这个Converter也太恶心了。

2.       Province类的Provincesget函数改写如下。

 

           get

           {

              return new ObservableCollection<Province>(allProvince);

    }

 

就是每次都实例化一个新的Collection喽。同时,还要把使用了这个属性的DataTemplatex:Shared设置为False这个也比较恶心。不过还好,也就多占用几个Collection本身的内存。

3.       自己写一个CollectionViewSoure,在View生成之后把ViewCurrentPosition设置为-1。试了一下,没做出来L

4.       Province类直接显露一个CollectionViewSource类型的省份数据源。并在get函数里先SetCurrentPosition-1return。目前来看这个方案是最佳的。

5.       跑去Microsoft Connect,报个Bug,看看微软的人怎么解释。还没有试。Connect网站太慢了。

 

整体而言这个还算是个小问题了。就是新手们可能遇到问题的时候会不知道是怎么回事,不知道为什么会有这个问题。

 

抱歉!评论已关闭.