簡體   English   中英

如何使用 ObservableCollection 數據過濾 treeview

[英]How to filter treeview with ObservableCollection data

我做了一個 treeview 示例,並希望獲得如下所示的結果:

有一組復選框(綠色、黃色和紅色)正在被選中。 然后,有一個 treeview。如您所見,如果其中一個子節點包含紅色/黃色,則它們的父節點也轉向相同的顏色節點。 例如,Class A 節點是紅色的,因為 Student 3 它的節點是紅色的。

在此處輸入圖像描述

如何在WPF c#中實現過濾樹視圖function?

示例結果,

如果我取消選中綠色復選框,結果將是:

在此處輸入圖像描述

如果我取消選中綠色和黃色,結果將是:

在此處輸入圖像描述

可以在這里獲取 treeview 樣本

TreeView樣品

主 Window XAML

<StackPanel Orientation="Vertical">
    <StackPanel Orientation="Vertical">
        <CheckBox Content="Green" Margin="2" />
        <CheckBox Content="Yellow" Margin="2" />
        <CheckBox Content="Red" Margin="2" IsChecked="True" />
    </StackPanel>
    <TreeView ItemsSource="{Binding ClassList}">
        <TreeView.Resources>
            <HierarchicalDataTemplate DataType="{x:Type loc:Class}" ItemsSource="{Binding Students}">
                <Border Width="150" BorderThickness="1" CornerRadius="2" Margin="2" Padding="2" >
                    <StackPanel Orientation="Horizontal" >
                        <TextBlock  Text="{Binding Name}" FontWeight="Bold"></TextBlock>
                        <Image Margin="2" Source="{Binding ImagePath}"></Image>
                    </StackPanel>
                </Border>
            </HierarchicalDataTemplate>

            <HierarchicalDataTemplate DataType="{x:Type loc:Student}">
                <Border Width="132" CornerRadius="2" Margin="1" >
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="*"></ColumnDefinition>
                            <ColumnDefinition Width="26"></ColumnDefinition>
                        </Grid.ColumnDefinitions>

                        <TextBlock Margin="2"  Text="{Binding Name}" ToolTip="{Binding ToolTip}"></TextBlock>

                        <Image Grid.Column="1" Margin="2" Source="{Binding ImagePath}"></Image>
                    </Grid>
                </Border>
            </HierarchicalDataTemplate>
        </TreeView.Resources>
    </TreeView>
</StackPanel>

因此,您需要跟蹤兩個集合-一個是“過濾的” ObservableCollcetion,另一個是“主”的ObservableCollection(具有COMPLETE樹)。

因此,無論何時綁定到TreeView的ItemsSource,都需要綁定到FilteredObservableCollection。 默認情況下,將使用MasterObservableCollection中的所有項目初始化此集合。

當某人更改Checkbox(並且其綁定反映在您的ViewModel中,即IsRed = false)時,您會在ViewModel上進行一些操作來更新FilteredObservableCollection。 您將清除FilteredObservableCollection中的所有項目,然后遍歷MasterObservableCollection,將符合條件的項目添加到其中。

因此,您的ViewModel提供了一些簡短的偽代碼...

ObservableCollection<MyItem> MasterCollection;
ObservableCollection<MyItem> FilteredCollection;
bool IsRed, IsYellow, IsGreen; 

UpdateFilteredCollection()
{
    FilteredCollection.Clear();

    foreach( MyItem item in MasterCollection )
    {
        if( ( item.Color == Green && IsGreen ) || ( item.Color == Yellow && IsYellow ) || ( item.Color == Red && IsRed ) )
        {
            FilteredCollection.Add( item );
            /*
               And do this for child items, etc -- you'll probably
               have to rebuild the tree/MyItem's since some items
               will not appear under their parents;

               So this might look more like:

            FilteredCollection.Add( new MyItem()
                                    {
                                       Color = item.Color,
                                       Label = item.Label 
                                    } );
            */
        }
    }
}

可以為 treeview 層次結構的所有節點設置過濾謂詞。 下面我提供了一個擴展方法,您可以調用它來設置過濾器 function,如下所示: myTreeView.Filter(FilterPredicate); . 當然在過濾謂詞中你需要區分你的分層數據model的不同類型的treeview節點。

您的謂詞可能如下所示:

private bool FilterPredicate(object node) {
  if (node is Students) {
    return true; // always show nodes of level 0
  }
  else if (node is Student) {
    return (node as Student).Name.StartsWith(_searchText);
  }
  return true;
}

這是 TreeViewItem 上的擴展方法,用於遞歸地在層次結構的所有 TreeViewItems 上設置過濾器:

public static class TreeViewExtensions {
    /// <summary>
    /// Applies a search filter to all items of a TreeView recursively
    /// </summary>
    public static void Filter(this TreeView self, Predicate<object> predicate)
    {
        ICollectionView view = CollectionViewSource.GetDefaultView(self.ItemsSource);
        if (view == null)
            return;
        view.Filter = predicate;
        foreach (var obj in self.Items) {
           var item = self.ItemContainerGenerator.ContainerFromItem(obj) as TreeViewItem;
           FilterRecursively(self, item, predicate);
        }
    }

    private static void FilterRecursively(TreeView tree, TreeViewItem item, Predicate<object> predicate)
    {
        ICollectionView view = CollectionViewSource.GetDefaultView(item.ItemsSource);
        if (view == null)
            return;
        view.Filter = predicate;
        foreach (var obj in item.Items) {
           var childItem = tree.ItemContainerGenerator.ContainerFromItem(obj) as TreeViewItem;
           FilterRecursively(tree, childItem, predicate);
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM