[英]HierarchicalDataTemplate TreeView - ContainerFromItem returns TreeViewItem only for the first Item
I have a TreeView as follows: 我有一个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>
In code behind, I am using the following xml as DataContext: 在后面的代码中,我使用以下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 is generating fine, but while enumerating the Items, I get TreeViewItem only for the first XmlNode(root node ie <a>
) and the remaining XmlNodes down in the hierarchy do not have any corresponding TreeViewItems present. TreeView生成的很好,但是在枚举Items时,我仅对第一个XmlNode(根节点即
<a>
)获得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();
}
Why the rest of the XmlNodes in the Tree do not have any TreeViewItem present? 为什么树中的其余XmlNodes没有任何TreeViewItem?
Any help is greatly appreciated. 任何帮助是极大的赞赏。
It's because the other items aren't in tv, they are in the 'a' TreeViewItem. 这是因为其他项目不在电视中,它们在“ a” TreeViewItem中。 But, they really are not in 'a' yet either because the TreeViewItem isn't expanded and the layout hasn't been updated.
但是,它们实际上还不在'a'中,这是因为TreeViewItem未展开且布局尚未更新。
You can make it work by passing in the ItemsControl (either tv or the parent TreeViewItem) and using it to get the ContainerFromItem. 您可以通过传入ItemsControl(电视或父级TreeViewItem)并使用它来获取ContainerFromItem来使其工作。 But, you will have to expand the item and update it's layout before you will get a container.
但是,您将必须扩展项目并更新其布局,然后才能获得容器。
Here is some code to do the above. 这是执行上述操作的一些代码。 A side effect will be that the tree is fully expanded.
副作用是树已完全展开。
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();
}
Actually, you only really need to pass in the ItemsControl. 实际上,您实际上只需要传递ItemsControl。 Also, I put some code in to close the tree back up.
另外,我输入了一些代码以关闭树备份。
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);
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.