如何访问TreeViewItem的子元素

时间:2018-04-11 12:53:02

标签: c# .net wpf treeview

我正在尝试将搜索功能添加到WPF中的TreeView。我成功地为一个只有一个级别的TreeView添加和搜索树项目,但对于具有多个级别的TreeView,我无法弄清楚如何访问一个子控件(UIElement)树型视图。当我将ItemContainerGenerator.ContainerFromItem()作为参数传递时,TreeViewItem.Item返回null。我看到几个帖子讨论了同样的问题,但没有一个解决方案适合我。

这是我的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 个答案:

答案 0 :(得分:1)

如果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或挂钩事件,也可能是其他一些内容。

答案 1 :(得分:0)

电视有一个节点集合。每个节点还有一个节点集合。

您需要从根开始,检查每个节点,以及该节点是否包含长度为&gt;的节点集合。 0,你需要进入它。

这通常使用递归树步行来完成。