先决条件:.NET 4.5.1
我有三个TreeView
显示单个集合实例的三个过滤变体的控件。当我尝试对 Items
应用过滤器时此过滤器自动传播到其他控件的控件之一的集合,这阻止我在不同的控件上使用不同的过滤器。
有什么方法可以实现相同的结果,而不必同时维护三个集合实例?
下面是一个显示问题的示例。前两个 ListView 直接绑定(bind)到同一个集合实例。第三个通过 CompositeCollection
绑定(bind)到该实例。 。第四是绑定(bind)独立采集。当我按下“设置过滤器”按钮时ItemsControl.Items.Filter
属性如果首先 ListView
设置为IsAllowedItem
WTest 窗口的方法。在这一秒之后istView.Items.Filter
属性以某种方式指向相同的方法,而第三个和第四个 ListView 返回 null。另一个影响是,虽然第三个 ListView
显示空过滤器,它的集合仍然被过滤,如果您运行该示例,您可以看到。这种非常奇怪的效果是由 ItemCollection 类基于 ItemsSource
时的行为引起的。所有者元素的属性获取底层 CollectionView
通过CollectionViewSource.GetDefaultCollectionView
从一些应用程序范围的存储中方法。我不知道这个实现的原因,但怀疑它的性能。
测试窗口WTest.xaml:
<Window x:Class="Local.WTest"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:c="clr-namespace:System.Collections;assembly=mscorlib"
xmlns:local="clr-namespace:Local"
Name="_WTest" Title="WTest" Height="300" Width="600">
<Window.Resources>
<c:ArrayList x:Key="MyArray">
<s:String>Letter A</s:String>
<s:String>Letter B</s:String>
<s:String>Letter C</s:String>
</c:ArrayList>
<CompositeCollection x:Key="MyCollection" >
<CollectionContainer Collection="{StaticResource ResourceKey=MyArray}"/>
</CompositeCollection>
<c:ArrayList x:Key="AnotherArray">
<s:String>Letter A</s:String>
<s:String>Letter B</s:String>
<s:String>Letter C</s:String>
</c:ArrayList>
</Window.Resources>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Name="FilterLabel1"/>
<TextBlock Grid.Row="0" Grid.Column="1" Name="FilterLabel2"/>
<TextBlock Grid.Row="0" Grid.Column="2" Name="FilterLabel3"/>
<TextBlock Grid.Row="0" Grid.Column="3" Name="FilterLabel4"/>
<ListView Grid.Row="1" Grid.Column="0" Name="View1" ItemsSource="{StaticResource ResourceKey=MyArray}"/>
<ListView Grid.Row="1" Grid.Column="1" Name="View2" ItemsSource="{StaticResource ResourceKey=MyArray}"/>
<ListView Grid.Row="1" Grid.Column="2" Name="View3" ItemsSource="{StaticResource ResourceKey=MyCollection}"/>
<ListView Grid.Row="1" Grid.Column="3" Name="View4" ItemsSource="{StaticResource ResourceKey=AnotherArray}"/>
<Button Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="4" Content="Set Filter" Click="OnSetFilterButtonClick"/>
</Grid>
</Window>
WTest.xaml.cs 背后的代码
namespace Local
{
using System.Windows;
public partial class WTest : Window
{
public WTest()
{
InitializeComponent();
UpdateFilterLabels();
}
private bool IsAllowedItem(object item)
{
return "Letter A" == (string)item;
}
private void OnSetFilterButtonClick(object sender, RoutedEventArgs e)
{
View1.Items.Filter = IsAllowedItem;
UpdateFilterLabels();
}
private void UpdateFilterLabels()
{
FilterLabel1.Text = (null == View1.Items.Filter) ? "No Filter" : View1.Items.Filter.Method.Name;
FilterLabel2.Text = (null == View2.Items.Filter) ? "No Filter" : View2.Items.Filter.Method.Name;
FilterLabel3.Text = (null == View3.Items.Filter) ? "No Filter" : View3.Items.Filter.Method.Name;
FilterLabel4.Text = (null == View4.Items.Filter) ? "No Filter" : View4.Items.Filter.Method.Name;
}
}
}
单击“设置过滤器”按钮后的结果: Example: result of clicking "Set Filter" button
最佳答案
创建
CollectionViewSource
作为资源
。<CollectionViewSource x:Key="CVSKey" Source="{DynamicResource MyArray}"/>
使用此
CollectionViewSource
作为您的ItemsSource
。将您的 View1 替换为:<!--<ListView Grid.Row="1" Grid.Column="0" Name="View1" ItemsSource="{DynamicResource ResourceKey=MyArray}"/>--> <ListView Grid.Row="1" Grid.Column="0" Name="View1" ItemsSource="{Binding Source={StaticResource ResourceKey=CVSKey}}"/>
就是这样,现在一切都会按照你想要的方式进行。
此外,现在您可以对此CollectionViewSource
而不是View1应用过滤:
((CollectionViewSource)this.Resources["CVSKey"]).Filter += List_Filter;
void List_Filter(object sender, FilterEventArgs e)
{
e.Accepted = (e.Item.ToString() == "Letter A") ? true : false;
}
为单独的ListBox
创建单独的CollectionViewSource
,以从同一底层集合创建单独的 View 。
在 google 中搜索 CollectionViewSource
。
关于c# - 单个集合上的多个 ItemControl 同时将过滤器应用于所有 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38542781/