代码之家  ›  专栏  ›  技术社区  ›  Suresh

如何访问TreeViewItem的子元素

  •  2
  • Suresh  · 技术社区  · 6 年前

    我正在尝试在WPF中向TreeView添加搜索功能。我成功地为只有一个级别的TreeView添加和搜索树项目,但对于具有多个级别的TreeView,我无法确定如何访问子控件( UIElement )树上的一个项目。 ItemContainerGenerator.ContainerFromItem() 当我通过时返回null TreeViewItem.Item 作为论据。我看到很少有帖子讨论同样的问题,但没有一个解决方案对我有效。

    这是我的XAML代码。

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="20" />
            <RowDefinition Height="72*" />
        </Grid.RowDefinitions>
        <StackPanel x:Name="SearchTextBox" Grid.Row="0"  Margin="5,5,5,0"/>
        <TreeView Name="MyTreeView" Grid.Row="1" BorderThickness="0">
            <TreeView.ItemTemplate>
                <HierarchicalDataTemplate ItemsSource="{Binding Students}">
                    <TextBlock Margin="3" Text="{Binding SchoolName}"/>
                    <HierarchicalDataTemplate.ItemTemplate>
                        <DataTemplate>
                                <TextBlock Text="{Binding StudentName}"/>
                        </DataTemplate>
                    </HierarchicalDataTemplate.ItemTemplate>
                </HierarchicalDataTemplate>
            </TreeView.ItemTemplate>
        </TreeView>
    </Grid>
    

    这是我的C代码

    public class MyClass
    {
        public string ClassName { get; set; }
        public List<Student> Students { get; set; }
    }
    
    public class Student
    {
        public string StudentName { get; set; }
    }
    
    private void PlanSearchOnSearchInputChanged(string searchQuery)
    {
        List<TreeViewItem> items = GetLogicalChildCollection(MyTreeView);
    }
    
    public static List<TreeViewItem> GetLogicalChildCollection(TreeView parent)
    {
        var logicalCollection = new List<TreeViewItem>();
        foreach (var child in parent.Items)
        {
            TreeViewItem item = (TreeViewItem)parent.ItemContainerGenerator.ContainerFromItem(child);
            logicalCollection.Add(item);
            GetLogicalChildCollection(item, logicalCollection);
        }
        return logicalCollection;
    }
    
    public static List<TreeViewItem> GetLogicalChildCollection(TreeViewItem parent, List<TreeViewItem> logicalCollection)
    {
        foreach (var child in parent.Items)
        {
            TreeViewItem item = (TreeViewItem)parent.ItemContainerGenerator.ContainerFromItem(child);
            logicalCollection.Add(item);
        }
        return logicalCollection;
    }
    

    PS:我需要访问项目的UIElement,而不仅仅是项目。 任何帮助都将不胜感激。

    2 回复  |  直到 6 年前
        1
  •  3
  •   Lauraducky    6 年前

    如果TreeViewItem未展开,则其子项将没有任何UI,因此您无法获取其子项。也许这就是你看到的问题。

    这是一些需要考虑的代码,我没有所有的代码来轻松地计算出发生了什么,但这在我的示例中有效。它是快速和肮脏的,而不是超级优雅。

    private void Button_Click(object sender, RoutedEventArgs e)
    {
        foreach (var item in tv.Items)
        {
            TreeViewItem tvi = tv.ItemContainerGenerator.ContainerFromItem(item) as TreeViewItem;
            tvi.IsExpanded = true;
            tvi.UpdateLayout();
            RecurseItem(tvi);
        }
    }
    
    private bool gotTheItem = false;
    private void RecurseItem(TreeViewItem item)
    {
        foreach (var subItem in item.Items)
        {
            TreeViewItem tvi = item.ItemContainerGenerator.ContainerFromItem(subItem) as TreeViewItem;
            // do something
            if (!gotTheItem)
            {
                RecurseItem(tvi);
            }
        }
    }
    

    你可以设置 IsExpanded 当您展开一个项目或其他一些东西时,返回或挂接事件激发。

        2
  •  0
  •   Terry Carmen    6 年前

    TV具有节点集合。每个节点还具有一个节点集合。

    您需要从根开始,检查每个节点,如果该节点包含长度为>0,您需要下降到其中。

    这通常通过递归树遍历来完成。