【问题标题】:HierarchicalDataTemplate TreeView - ContainerFromItem returns TreeViewItem only for the first ItemHierarchicalDataTemplate TreeView - ContainerFromItem 只为第一个项目返回 TreeViewItem
【发布时间】:2016-09-13 11:49:48
【问题描述】:

我有一个 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(根节点,即&lt;a&gt;)获取 TreeViewItem,而层次结构中剩余的 XmlNodes 没有任何对应的 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?

非常感谢任何帮助。

【问题讨论】:

    标签: c# wpf treeview


    【解决方案1】:

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

    您可以通过传入 ItemsControl(电视或父 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);
    }
    

    【讨论】:

    • 非常感谢。我会试试这个。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-10-06
    • 1970-01-01
    • 1970-01-01
    • 2016-08-04
    • 1970-01-01
    • 2010-10-11
    • 2011-07-10
    相关资源
    最近更新 更多