2016-09-13 84 views
2

我有一個TreeView如下:HierarchicalDataTemplate的TreeView - ContainerFromItem返回樹型視圖只針對第一項

<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的是生成罰款,但枚舉的項目,我得到TreeViewItem只爲第一個XmlNode(根節點,即<a>)和層次結構中剩下的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(); 
} 

爲什麼樹中其餘的XmlNodes沒有任何TreeViewItem存在?

任何幫助,非常感謝。

回答

3

這是因爲其他項目不在電視中,它們在'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); 
} 
+0

非常感謝。我會試試這個。 – teenup