我有一个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生成正常,但在枚举Items时,我只为第一个XmlNode(根节点,即<a>
)获取TreeViewItem,并且层次结构中的其余XmlNodes没有任何相应的TreeViewItem存在。
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();
}
为什么Tree中的其余XmlNode没有任何TreeViewItem?
非常感谢任何帮助。
答案 0 :(得分:3)
这是因为其他项目不在电视中,而是在&#39; a&#39;树型视图。但是,他们真的不在&#39; a&#39;但要么是因为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);
}