我正在为集合制作一个过滤器.
我知道如何使用 CollectionViewSource.
但我想在不使用 CVS.
根据我的想法,ItemsControl.Items 属性中有一个 CollectionView,您可以使用此属性的方法.
可以毫无问题地添加过滤器.
但是调用 Items.Refresh() 后没有任何变化。
简单的例子:
<UniformGrid Columns="2">
<FrameworkElement.Resources>
<sc:StringCollection
x:Key="coll">
<sys:String>112</sys:String>
<sys:String>22</sys:String>
<sys:String>33</sys:String>
<sys:String>114</sys:String>
<sys:String>411</sys:String>
</sc:StringCollection>
<CollectionViewSource
x:Key="cvs"
Source="{Binding Mode=OneWay, Source={StaticResource coll}}"
Filter="OnFilterCV"/>
</FrameworkElement.Resources>
<TextBox x:Name="tBox"
Text="1"
TextChanged="OnTextChanged"
VerticalAlignment="Center"/>
<TextBox x:Name="tBoxCV"
Text="1"
TextChanged="OnTextChangedCV"
VerticalAlignment="Center"/>
<ItemsControl x:Name="iCtrl"
ItemsSource="{Binding Mode=OneWay, Source={StaticResource coll}}">
</ItemsControl>
<ItemsControl x:Name="iCtrlCV"
ItemsSource="{Binding Mode=OneWay, Source={StaticResource cvs}}">
</ItemsControl>
</UniformGrid>
public partial class MainWindow : Window
{
private readonly CollectionViewSource cvs;
public MainWindow()
{
InitializeComponent();
iCtrl.Items.Filter = OnFilter;
cvs = (CollectionViewSource)iCtrlCV.FindResource("cvs");
}
private bool OnFilter(object obj)
{
if (string.IsNullOrWhiteSpace(tBox.Text))
return true;
string item = (string)obj;
return item.Contains(tBox.Text, StringComparison.OrdinalIgnoreCase);
}
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
Debug.WriteLine($"OnTextChanged:"{tBox.Text}"");
iCtrl?.Items.Refresh();
}
private void OnFilterCV(object sender, FilterEventArgs e)
{
e.Accepted = string.IsNullOrWhiteSpace(tBoxCV.Text) ||
((string)e.Item).Contains(tBoxCV.Text, StringComparison.OrdinalIgnoreCase);
}
private void OnTextChangedCV(object sender, TextChangedEventArgs e)
{
Debug.WriteLine($"OnTextChangedCV:"{tBoxCV.Text}"");
cvs?.View.Refresh();
}
}
我是否误解了什么或做错了什么?
更新。基于@BionicCode评论的解决方案。
private void OnTextChanged(object sender, TextChangedEventArgs e)
{
Debug.WriteLine($"OnTextChanged:"{tBox.Text}"");
//iCtrl?.Items.Refresh();
if (iCtrl != null)
iCtrl.Items.Filter = new Predicate<object>(OnFilter);
}
ItemsControl.Items
的类型为ItemsCollection
。ItemsCollection
实现不同的Refresh
行为。Items
属性基本上供内部使用。如果必须依赖CollectionView.Refresh
则应显式使用该CollectionView
:
ItemsControl itemsControl;
itemsControl.Items.Filter = item => (item as string).Contains("A");
CollectionView collectionView = CollectionViewSource.GetDefaultView(itemsControl.ItemsSource);
collectionView.Refresh();