wpf 如何使用ObservableCollection数据筛选树视图

2hh7jdfx  于 2022-11-26  发布在  其他
关注(0)|答案(2)|浏览(466)

我已经做了一个树形视图示例,并希望得到如下所示的结果:
有一组复选框(绿色、黄色和红色)并被选中。然后,有一个树视图。正如你所看到的,如果它的一个子节点包含红色/黄色,它们的父节点也会变成相同颜色的节点。例如,班级A的节点是红色的,因为学生3的节点是红色的。

如何在WPF C#中实现过滤树视图功能?
实施例结果,
如果我取消选中“绿色”复选框,结果将是:

如果我未选中绿色和黄色,结果将是:

可以在此处获取treeview示例
TreeView Sample

主窗口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>
wrrgggsh

wrrgggsh1#

因此,您需要跟踪两个集合--一个是“Filtered”ObservableCollction,另一个是“Master”ObservableCollection(它具有COMPLETE树)。
因此,无论何时绑定到TreeView的ItemsSource,都需要绑定到FilteredObservableCollection。默认情况下,此集合将使用MasterObservableCollection中的所有项进行初始化。
当有人更改了一个复选框(它的绑定反映在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 
                                    } );
            */
        }
    }
}
pxy2qtax

pxy2qtax2#

可以为树形视图层次结构的所有节点设置过滤 predicate 。下面我提供了一个扩展方法,您可以调用它来设置过滤函数,如下所示:当然,在过滤 predicate 中,您需要区分层次数据模型中不同类型的树视图节点。
predicate 可能如下所示:

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上的扩展方法,用于以递归方式在层次结构的所有TreeViewItem上设置筛选器:

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);
        }
    }
}

相关问题