c# - HierarchicalDataTemplate TreeView - ContainerFromItem 仅返回第一个 Item 的 TreeViewItem

标签 c# wpf treeview

我有一个 TreeView 如下:

<TreeView
    Loaded="tv_Loaded_1"
    DockPanel.Dock="Bottom"
    Name="tv"
    ItemsSource="{Binding XPath=*}">
    <TreeView.ItemTemplate>
        <HierarchicalDataTemplate
            ItemsSource="{Binding XPath=*}">
            <StackPanel
                Orientation="Horizontal">
                <TextBlock
                    Text="{Binding Name}"></TextBlock>
            </StackPanel>
        </HierarchicalDataTemplate>
    </TreeView.ItemTemplate>
</TreeView>

在后面的代码中,我使用以下 xml 作为 DataContext:

XmlDocument doc = new XmlDocument();
doc.LoadXml(@"<a><b><c></c><d></d></b><e><f></f><g></g></e></a>");
DataContext = doc;

TreeView 生成正常,但在枚举项目时,我仅获得第一个 XmlNode(根节点,即 <a> )的 TreeViewItem,而层次结构中其余的 XmlNode 没有任何相应的 TreeViewItems。

private IEnumerable<TreeViewItem> Enumerate(ItemCollection items)
{
    foreach (XmlElement element in items)
    {
        TreeViewItem item = tv.ItemContainerGenerator.ContainerFromItem(element) as TreeViewItem;
        if (item != null) //When second call with <a>.Items, item is null
        {
            yield return item;
        }
        //Enumerate is called again with <a>.Items 
        //Exception in second call, because item is null
        foreach (TreeViewItem i in Enumerate(item.Items))
        {
            yield return i;
        }
    }
}

private void tv_Loaded_1(object sender, RoutedEventArgs e)
{
   var list = Enumerate(tv.Items).ToList();
}

为什么树中的其余 XmlNode 没有任何 TreeViewItem 存在?

非常感谢任何帮助。

最佳答案

这是因为其他项目不在 tv 中,而是在“a”TreeViewItem 中。但是,它们实际上也不在“a”中,因为 TreeViewItem 尚未展开并且布局尚未更新。

您可以通过传入 ItemsControl(tv 或父 TreeViewItem)并使用它来获取 ContainerFromItem 来使其工作。但是,您必须先展开该项目并更新其布局,然后才能获得容器。

这里是一些执行上述操作的代码。副作用是树完全展开。

private IEnumerable<TreeViewItem> Enumerate(ItemsControl itemsControl, ItemCollection items)
{
    foreach (XmlElement element in items)
    {
        TreeViewItem item = itemsControl.ItemContainerGenerator.ContainerFromItem(element) as TreeViewItem;
        if (item != null) //When second call with <a>.Items, item is null
        {
            item.IsExpanded = true;
            item.UpdateLayout();

            yield return item;
        }
        //Enumerate is called again with <a>.Items 
        //Exception in second call, because item is null
        foreach (TreeViewItem i in Enumerate(item, item.Items))
        {
            yield return i;
        }
    }
}

private void tv_Loaded_1(object sender, RoutedEventArgs e)
{
    var list = Enumerate(tv, tv.Items).ToList();
}

实际上,您只需要传入 ItemsControl 即可。另外,我还添加了一些代码来关闭树备份。

private IEnumerable<TreeViewItem> Enumerate(ItemsControl itemsControl)
{
    foreach (XmlElement element in itemsControl.Items)
    {
        TreeViewItem item = itemsControl.ItemContainerGenerator.ContainerFromItem(element) as TreeViewItem;
        if (item != null) //When second call with <a>.Items, item is null
        {
            item.IsExpanded = true;
            item.UpdateLayout();

            yield return item;
        }
        //Enumerate is called again with <a>.Items 
        //Exception in second call, because item is null
        foreach (TreeViewItem i in Enumerate(item))
        {
            yield return i;
        }
    }
}

private void tv_Loaded_1(object sender, RoutedEventArgs e)
{
    var list = Enumerate(tv).ToList();
    // Unexpand all the items
    list.ForEach(tvi => tvi.IsExpanded = false);
}

关于c# - HierarchicalDataTemplate TreeView - ContainerFromItem 仅返回第一个 Item 的 TreeViewItem,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39469335/

相关文章:

c# - wpf TreeView 蓝调。我要选择一个项目

jQuery 树结构

c# - 从服务器端 ASP.Net 将 Javascript 函数绑定(bind)到 TreeView CheckBox

c# - Tridion 2011 : Changing a page's file name as it's being published

c# - 创建一个返回 Razor @ 标签的辅助函数?

c# - 如何让父类知道其子类的变化?

c# - 如何确定 System.Object 是否为 System.Type

c# - 我应该如何使用 IoC/依赖注入(inject)来处理我的实体/域对象?

c# - 使用 System.Net.Mail lib 发送的电子邮件显示中文字母

c# - 我们可以在 ASP.NET Web 应用程序项目中使用 WPF 控件吗?