我有一个 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/