Необходимые условия: .NET 4.5.1Multiple ItemsControl на одной коллекции применяется фильтр ко всем представлениям сразу
У меня есть 3 элементов управления TreeView, отображающие дерево фильтруется варианты одного экземпляра коллекции. Когда я пытаюсь применить фильтр в коллекции Items одного из элементов управления, этот фильтр распространяется на другие элементы управления автоматически, что мешает мне использовать разные фильтры для разных элементов управления. Есть ли способ достичь такого же результата без необходимости одновременного хранения экземпляров деревьев?
Ниже приведен пример, который показывает проблему. Первые два ListViews привязаны к одному экземпляру коллекции напрямую. Третий связан с этим экземпляром через CompositeCollection. И четвертый связан с независимой коллекцией. Когда я нажимаю кнопку «Установить фильтр», свойство ItemsControl.Items.Filter, если в первом списке ListView установлен метод IsAllowedItem окна WTest. После этого второго свойства ListView.Items.Filter каким-то образом указывает на тот же метод, в то время как третий и четвертый ListView возвращает null. Другим эффектом является то, что хотя третий ListView отображает нулевой фильтр, его коллекция по-прежнему фильтруется, как вы можете видеть, запускаете ли вы пример. Этот очень странный эффект возникает из-за поведения класса ItemCollection, который, основываясь на свойстве ItemsSource элемента owner, приобретает базовый CollectionView из некоторого хранилища в аппликационном пространстве с помощью метода CollectionViewSource.GetDefaultCollectionView. Я не знаю причины этой реализации, но подозреваю, что это производительность.
Test окно 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. –