2016-07-23 2 views
1

前提条件を一度にすべてのビューにフィルタを適用します。コントロールのItemsコレクションにフィルターを適用しようとすると、このフィルターは他のコントロールに自動的に伝播し、異なるコントロールで異なるフィルターを使用できなくなります。 コレクションのツリーインスタンスを一度に維持する必要がなく、同じ結果を達成する方法はありますか?複数のItemsControlは

この問題を示す例を以下に示します。最初の2つのListViewは、同じコレクションインスタンスに直接バインドされています。 3番目のインスタンスは、CompositeCollectionを介してそのインスタンスにバインドされています。そして4番目は独立したコレクションにバインドされています。最初のListViewがWTestウィンドウのIsAllowedItemメソッドに設定されている場合、 "Set Filter"ボタンItemsControl.Items.Filterプロパティを押します。この2番目のListView.Items.Filterプロパティは、3番目と4番目のListViewがnullを返す間、何らかの方法で同じメソッドを指しています。もう1つの効果は、3番目のListViewにnullフィルタが表示されますが、その例を実行するとわかるように、そのコレクションはまだフィルタリングされています。この非常に奇妙な結果は、ItemCollectionクラスの動作から発生します。これは、owner要素のItemsSourceプロパティに基づいて、アプリケーション全体のストレージからCollectionViewSource.GetDefaultCollectionViewメソッドを介して基礎となるCollectionViewを取得することです。私はこの実装の理由を知らないが、それがパフォーマンスであると思われる疑いがある。

テストウィンドウWTest.xaml:WTest.xaml.cs

背後

<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> 

コード

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

答えて

0
  1. ResourceとしてCollectionViewSourceを作成します。

    <CollectionViewSource x:Key="CVSKey" Source="{DynamicResource MyArray}"/>

  2. このCollectionViewSourceItemsSourceとして使用してください。あなた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}}"/> 
    

、今ではすべてが動作します。

また、今あなたの代わりにView1をのこのCollectionViewSourceにフィルタリングを適用することができます。

((CollectionViewSource)this.Resources["CVSKey"]).Filter += List_Filter; 

void List_Filter(object sender, FilterEventArgs e) 
    { 
     e.Accepted = (e.Item.ToString() == "Letter A") ? true : false; 
    } 

同じ基になるコレクションから別のビューを作成するために別のListBoxes用に別のCollectionViewSourceを作成します。

google for CollectionViewSourceを検索してください。

+0

、ありがとう、CollectionViewSourceのプロキシが役立ちました。 –

0

変更OnSetFilterButtonClick以下のような方法

private void OnSetFilterButtonClick(object sender, RoutedEventArgs e) 
     { 
      //Create a new listview by the ItemsSource,Apply Filter to the new listview 
      ListCollectionView listView = new ListCollectionView(View1.ItemsSource as IList); 
      listView.Filter = IsAllowedItem; 
      View1.ItemsSource = listView; 
      UpdateFilterLabels(); 
     } 
+0

1つのコレクションは、1つのコレクションビューをバインドする1つのリストボックスを作成できます。 – zhaojingbo

関連する問題