[英]CollectionViewSource, how to filter data?
我正在將 ComboBox 綁定到實體,但我想要過濾數據。
到目前為止,我嘗試了兩種方法:
我對第一種方法感到滿意,最重要的是因為生成到數據庫的查詢包含一個 WHERE 子句,因此不必從遠程數據庫中檢索所有數據....
但是,#2 方法要靈活得多,如果在運行時我想更改應用的過濾...我已經按照 msdn 上的示例進行操作,但出現異常,為什么?
所以,我的問題是:
1. 哪種方法更好
2. 為什么會出現異常?
這是我的代碼:
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;
}
}
}
編輯:我嘗試在視圖上實現過濾器屬性而不是設置事件處理程序:
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 值)
編輯
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 綁定中,而不是在背后的代碼中...
檢查這個
過濾需要一個委托(Predicate),過濾將基於它發生。 Predicate 根據它返回的值 true 或 false 接收項目 an,它選擇或取消選擇一個元素。
this.Source.Filter = item => {
ViewItem vitem = item as ViewItem;
return vItem != null && vitem.Name.Contains("A");
};
2) 動態過濾數據
最后我找到了一個解決方案,正如在這個問題中也發布的那樣,明確聲明集合的類型:
CollectionViewType="ListCollectionView"
所以在 XAML 中添加了 Collection 類型:
<CollectionViewSource x:Key="tSCHEDEViewSource" d:DesignSource="{d:DesignInstance my:TSCHEDE, CreateList=True}" CollectionViewType="ListCollectionView">
</CollectionViewSource>
現在在代碼中,事件處理程序起作用了:
myCollectionViewSource.Filter += new FilterEventHandler(filterSource);
唯一的遺憾是我不明白為什么,對於顯然如此簡單的事情,我必須在 XAML 中“手動”強制它??? 對我來說,這似乎是一種黑客行為,而且很容易出錯......
<TextBox x:Name="FilterTextBox">
<b:Interaction.Triggers>
<b:EventTrigger EventName="TextChanged">
<b:CallMethodAction
MethodName="Refresh"
TargetObject="{Binding View, BindsDirectlyToSource=True, Source={StaticResource tSCHEDEViewSource}}" />
</b:EventTrigger>
</b:Interaction.Triggers>
</TextBox>
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.