CollectionViewSource,如何过滤数据? [英] CollectionViewSource, how to filter data?
问题描述
我正在将 ComboBox 绑定到实体,但我想要过滤数据.
I am binding a ComboBox to Entities but I want the data filtered.
到目前为止,我尝试了两种方法:
Up to now I have tried two ways:
- 简单"一:通过过滤器直接应用到ObjectSetLINQ 到实体
- 如上所述设置过滤事件处理程序msdn
我对第一种方法感到满意,最重要的是因为生成到数据库的查询包含一个 WHERE 子句,因此不必从远程数据库中检索所有数据....
I am satisfied by the first approach, above all because the query generated to the database contains a WHERE clause, so not all the whole data have to be retrieved from the remote db....
但是,#2 方法要灵活得多,如果在运行时我想更改应用的过滤...我已经按照 msdn 上的示例进行操作,但出现异常,为什么?
However, the #2 approach is by far more flexible, if at runtime i'd like to change the filtering applied... I have followed the example on msdn, but I get an exception, why?
所以,我的问题是:
1. 哪种方法更好
2. 为什么会出现异常?
So, my questions are:
1. Which approach is better
2. Why I get the exception?
这是我的代码:
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
//Do not load your data at design time.
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
//Load your data here and assign the result to the CollectionViewSource.
System.Windows.Data.CollectionViewSource myCollectionViewSource =
(System.Windows.Data.CollectionViewSource)
this.Resources["tSCHEDEViewSource"];
// If I use this I get the data filtered on startup, but is it the right mode?
//myCollectionViewSource.Source = _context.TSCHEDE.Where(s => s.KLINEA == kLinea && s.FCANC == "T").OrderBy(s => s.DSCHEDA).OrderByDescending(s => s.DSTORICO);
// Instead If I apply my custom filtering logic
myCollectionViewSource.Filter += new FilterEventHandler(filterSource);
myCollectionViewSource.Source = _context.TSCHEDE; // ... Here i get an exception:
// 'System.Windows.Data.BindingListCollectionView' view does not support filtering. ???
}
}
private void filterSource(object sender, FilterEventArgs e)
{
TSCHEDE scheda = e.Item as TSCHEDE;
if (scheda != null)
{
if (scheda.KLINEA == 990)
{
e.Accepted = true;
}
else
{
e.Accepted = false;
}
}
}
编辑:我尝试在视图上实现过滤器属性而不是设置事件处理程序:
EDIT: I have tried implementing the Filter property on the View rather than setting the EventHandler:
myCollectionView = (BindingListCollectionView)myCollectionViewSource.View;
myCollectionView.Filter = new Predicate<object>(Contains);
public bool Contains(object de)
{
TSCHEDE scheda = de as TSCHEDE;
return (scheda.KLINEA == 990);
}
现在我得到了不太有用的异常:
System.NotSupportedException:不支持指定的方法.在 System.Windows.Data.CollectionView.set_Filter(Predicate`1 值)
System.NotSupportedException: Specified method is not supported. at System.Windows.Data.CollectionView.set_Filter(Predicate`1 value)
编辑
XAML 代码:
<UserControl.Resources>
<CollectionViewSource x:Key="tSCHEDEViewSource" d:DesignSource="{d:DesignInstance my:TSCHEDE, CreateList=True}" >
</CollectionViewSource>
<DataTemplate x:Key="SchedaTemplate">
<StackPanel Orientation="Horizontal" >
<TextBlock Text="{Binding Path=KSCHEDA}" Width="60"></TextBlock>
<TextBlock Text="{Binding Path=DArticolo}" Width="200"></TextBlock>
<TextBlock Text=" - " Width="40"></TextBlock>
<TextBlock Text="{Binding Path=DSTORICO}" Width="150"></TextBlock>
</StackPanel>
</DataTemplate>
</UserControl.Resources>
<Grid Background="PapayaWhip" DataContext="{StaticResource tSCHEDEViewSource}" DataContextChanged="StartHere" Name="rootGrid">
<ComboBox ItemTemplate="{StaticResource SchedaTemplate}" Grid.Column="1" Grid.Row="1" Height="23" HorizontalAlignment="Left" ItemsSource="{Binding}" Margin="23,129,0,0" Name="tSCHEDEComboBox1" SelectedValuePath="KSCHEDA" VerticalAlignment="Top" Width="393">
<ComboBox.ItemsPanel>
<ItemsPanelTemplate>
<VirtualizingStackPanel />
</ItemsPanelTemplate>
</ComboBox.ItemsPanel>
</ComboBox>
</Grid>
现在我认为问题出在 XAML 绑定中,而不是在代码背后......
推荐答案
最后我找到了一个解决方案,同样发布了 在这个问题中显式声明集合的类型:
Al last I have found a solution, as posted also in this question to explicitly declare the type of the Collection:
CollectionViewType="ListCollectionView"
所以在 XAML 中添加了 Collection 类型:
So in XAML added the Collection type:
<CollectionViewSource x:Key="tSCHEDEViewSource" d:DesignSource="{d:DesignInstance my:TSCHEDE, CreateList=True}" CollectionViewType="ListCollectionView">
</CollectionViewSource>
现在在代码中事件处理程序起作用了:
And in code now the Event Handler works:
myCollectionViewSource.Filter += new FilterEventHandler(filterSource);
唯一的遗憾是我不明白为什么,对于看起来如此简单的事情,我必须在 XAML 中手动"强制它???对我来说,这似乎是一种黑客行为,而且很容易出错......
The only regret is that I did not understand why, for something apparently so simple, I have to force it "by hand" in XAML ??? To me this seems like an hack, and also very error prone...
这篇关于CollectionViewSource,如何过滤数据?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!