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

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网站太慢了。

 

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

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,关于 WPF 中 CollectionViewSource 与 ListBox 的折叠、分组显示,以及输入关键字 Filter 的筛选,可以通过以下步骤实现: 1. 首先,在 XAML 中创建一个 ListBox 控件,并通过 ItemsSource 绑定一个集合,例如: ```xml <ListBox ItemsSource="{Binding Items}"> <!-- ListBox 的其他属性和事件 --> </ListBox> ``` 2. 接着,定义一个 CollectionViewSource 对象,用于对集合进行折叠、分组和筛选等操作,例如: ```xml <Window.Resources> <CollectionViewSource x:Key="MyCollectionViewSource" Source="{Binding Items}"> <!-- CollectionViewSource 的其他属性 --> </CollectionViewSource> </Window.Resources> ``` 3. 然后,将 ListBox 的 ItemsSource 属性绑定CollectionViewSourceView 属性,例如: ```xml <ListBox ItemsSource="{Binding Source={StaticResource MyCollectionViewSource}}"> <!-- ListBox 的其他属性和事件 --> </ListBox> ``` 4. 在 CollectionViewSource 中,可以通过设置 GroupDescriptions 属性实现分组显示,例如: ```xml <CollectionViewSource.GroupDescriptions> <PropertyGroupDescription PropertyName="Category" /> </CollectionViewSource.GroupDescriptions> ``` 上面的代码表示按照集合中每个元素的 Category 属性进行分组显示。 5. 在 CollectionViewSource 中,可以通过设置 Filter 属性实现关键字筛选,例如: ```xml <CollectionViewSource.Filter> <Predicate<object> x:TypeArguments="object"> <![CDATA[ (string.IsNullOrEmpty(FilterText) || ((string)GetPropertyValue(item, FilterPropertyName) ?? string.Empty) .IndexOf(FilterText, StringComparison.OrdinalIgnoreCase) >= 0) ]]> </Predicate<object> </CollectionViewSource.Filter> ``` 上面的代码表示根据 FilterText 属性中的关键字对集合中的元素进行筛选,其中 GetPropertyValue 方法用于获取元素的指定属性值。 至此,就可以通过 CollectionViewSource 和 ListBox 实现折叠、分组和筛选等功能了。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值