C# HierarchycalDataTemplate TreeView-ContainerFromItem仅为第一个项返回TreeView项

C# HierarchycalDataTemplate TreeView-ContainerFromItem仅为第一个项返回TreeView项,c#,wpf,treeview,C#,Wpf,Treeview,我有一个树状视图,如下所示: <TreeView Loaded="tv_Loaded_1" DockPanel.Dock="Bottom" Name="tv" ItemsSource="{Binding XPath=*}"> <TreeView.ItemTemplate> <HierarchicalDataTemplate ItemsSource="{Binding XPath=*}"&

我有一个树状视图,如下所示:

<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作为数据上下文:

XmlDocument doc = new XmlDocument();
doc.LoadXml(@"<a><b><c></c><d></d></b><e><f></f><g></g></e></a>");
DataContext = doc;
XmlDocument doc=新的XmlDocument();
doc.LoadXml(@“);
DataContext=doc;
TreeView生成的结果很好,但在枚举项时,我只为第一个XmlNode(根节点,即
)获取TreeView项,层次结构中的其余XmlNodes没有任何对应的TreeView项

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();
}
private IEnumerable枚举(ItemCollection项)
{
foreach(项目中的XmlElement)
{
TreeView项目=tv.ItemContainerGenerator.ContainerFromItem(元素)作为TreeView项目;
if(item!=null)//第二次调用.Items时,item为null
{
收益回报项目;
}
//使用.Items再次调用枚举
//第二次调用中出现异常,因为项为null
foreach(枚举中的TreeViewItem i(item.Items))
{
收益率i;
}
}
}
已加载私有无效电视(对象发送器,路由目标)
{
var list=Enumerate(tv.Items).ToList();
}
为什么树中的其余XmlNodes没有任何TreeViewItem


非常感谢您的帮助。

因为其他项目不在电视中,它们在“a”树项目中。但是,它们也不是“a”,因为TreeViewItem没有扩展,布局也没有更新

您可以通过传入ItemsControl(tv或父树eviewitem)并使用它获取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();
}
private IEnumerable枚举(ItemsControl ItemsControl,ItemCollection items)
{
foreach(项目中的XmlElement)
{
TreeViewItem item=itemsControl.ItemContainerGenerator.ContainerFromItem(元素)作为TreeViewItem;
if(item!=null)//第二次调用.Items时,item为null
{
item.IsExpanded=true;
item.UpdateLayout();
收益回报项目;
}
//使用.Items再次调用枚举
//第二次调用中出现异常,因为项为null
foreach(枚举中的TreeViewItem i(项,项.项))
{
收益率i;
}
}
}
已加载私有无效电视(对象发送器,路由目标)
{
var list=枚举(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);
}
private IEnumerable枚举(ItemsControl ItemsControl)
{
foreach(itemsControl.Items中的XmlElement元素)
{
TreeViewItem item=itemsControl.ItemContainerGenerator.ContainerFromItem(元素)作为TreeViewItem;
if(item!=null)//第二次调用.Items时,item为null
{
item.IsExpanded=true;
item.UpdateLayout();
收益回报项目;
}
//使用.Items再次调用枚举
//第二次调用中出现异常,因为项为null
foreach(枚举中的TreeViewItem i(项目))
{
收益率i;
}
}
}
已加载私有无效电视(对象发送器,路由目标)
{
var list=Enumerate(tv.ToList();
//取消展开所有项目
list.ForEach(tvi=>tvi.IsExpanded=false);
}

非常感谢。我试试这个。