2012-04-30 23 views
2

我試圖找到特定的TreeViewItem,其Tag屬性設置爲特定值。如果父母TreeViewItem已展開,以下FindNode僅適用於一級項目或其他級別。在下面的示例中,如果「FFF」被展開,則FindNode按預期工作。我假設ContainerFromItem返回null,因爲項目尚未創建。有沒有辦法強制創建所有的TreeViewItems?如何在其Tag屬性中找到具有特定值的TreeViewItem

<TreeView x:Name="__items"> 

     <TreeViewItem Header="AAA" 
         Tag="{x:Static my:Node.A}" /> 

     <TreeViewItem Header="BBB" 
         Tag="{x:Static my:Node.B}"> 

      <!-- Items will be added later. --> 

     </TreeViewItem> 

     <TreeViewItem Header="CCC" 
         Tag="{x:Static my:Node.C}" /> 

     <TreeViewItem Header="DDD" 
         Tag="{x:Static my:Node.D}" /> 

     <TreeViewItem Header="EEE" 
         Tag="{x:Static my:Node.E}" /> 

     <TreeViewItem Header="FFF" 
         Tag="{x:Static my:Node.F}"> 

      <TreeViewItem Header="GGG" 
          Tag="{x:Static my:Node.G}" /> 

      <TreeViewItem Header="HHH" 
          Tag="{x:Static my:Node.H}" /> 

     </TreeViewItem> 

     <TreeViewItem Header="III" 
         Tag="{x:Static my:Node.I}" /> 

    </TreeView> 

public partial class MainWindow : Window 
{ 
    public MainWindow() 
    { 
     InitializeComponent(); 
     this.Loaded += new RoutedEventHandler(MainWindow_Loaded);  
    } 

    private void MainWindow_Loaded(object sender, RoutedEventArgs e) 
    { 
     TreeViewItem a = FindNode(__items.ItemContainerGenerator, __items.Items, Node.H); 
    } 

    private TreeViewItem FindNode(ItemContainerGenerator gen, ItemCollection items, Node value) 
    { 
     TreeViewItem oResult = null; 

     foreach (var oItem in items) 
     { 
      TreeViewItem oTreeViewItem = (TreeViewItem)gen.ContainerFromItem(oItem); 

      if (oTreeViewItem == null) { continue; } 

      if ((Node)oTreeViewItem.Tag == value) { oResult = oTreeViewItem; break; } 

      if (oTreeViewItem.Items.Count > 0) 
      { 
       oResult = FindNode(oTreeViewItem.ItemContainerGenerator, oTreeViewItem.Items, value); 

       if (oResult != null) { break; } 
      } 
     } 
     return oResult; 
    } 

} 

public enum Node { A, B, C, D, E, F, G, H, I, J, } 

基於hbarck的答案正確FindNode實現:

private TreeViewItem FindNode(ItemCollection items, Node value) 
    { 
     TreeViewItem oResult = null; 

     foreach (var oItem in items) 
     { 
      TreeViewItem oTreeViewItem = (TreeViewItem)oItem; 

      if ((Node)oTreeViewItem.Tag == value) { oResult = oTreeViewItem; break; } 

      if (oTreeViewItem.Items.Count > 0) 
      { 
       oResult = FindNode(oTreeViewItem.Items, value); 

       if (oResult != null) { break; } 
      } 
     } 
     return oResult; 
    } 
+0

爲什麼不使用MVVM模式有什麼特別的理由嗎? WPF的TreeView在與MVVM一起使用時效果很好。以另一種方式使用它可能非常難看,並給你一種'這太難了,我可能做錯了'的感覺。當你找到具有特定標籤的TreeViewItem時,你打算在代碼中做什麼? – Stipo

+0

我繼承的遺留代碼。爲了接受視圖模型,我試圖理清spagetti以獲得代碼基礎。 (目前,有多個視圖模型和代碼隱藏的混合體。)我需要查找項目,因爲它們目前在報價/不引用視圖模型中進行了硬編碼。 – AMissico

回答

0

確保您的TreeViewItems存在的最簡單方法可能是在它們每個上設置IsExpanded =「True」,並在TreeView上將IsVirtualizing設置爲False。出於好奇:如果你不使用ItemGenerator會發生什麼,但是直接迭代Items集合呢?既然你沒有使用DataTemplate,我會想象Items集合應該包含你的XAML文件中的硬編碼項目。

我已經做了以下測試:

<Window x:Class="MainWindow" 
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
Title="MainWindow" Height="350" Width="525"> 
<StackPanel> 
    <TreeView x:Name="TestTreeView"> 
     <TreeViewItem Header="Item 1"> 
      <TreeViewItem Header="Item 1 1"/> 
      <TreeViewItem Header="Item 1 2"/> 
     </TreeViewItem> 
     <TreeViewItem Header="Item 2"/> 
    </TreeView> 
    <Button x:Name="TestButton" Click="TestButton_Click">Test</Button> 
</StackPanel> 
</Window> 

和後面的代碼:

Class MainWindow 

    Private Sub TestButton_Click(sender As System.Object, e As System.Windows.RoutedEventArgs) 

     Stop 
     For Each t As TreeViewItem In Me.TestTreeView.Items 
      Debug.Print("Item: {0}, Child count:{1}", t.Header, t.Items.Count) 
     Next 
    End Sub 
End Class 

在調試窗口的輸出是

Item: Item 1, Child count:2 
Item: Item 2, Child count:0 

這意味着該項目是實例化並且可以迭代,即使在子級別中也是如此。 ItemContainerGenerator實際上只是在您使用DataTemplates時才需要的。此外,您可能必須等待窗口的Loaded事件後才能實例化所有項目。

+0

無論ItemGenerator如何,我都可以迭代第一級項目。現在我正在使用「IsExpanded = True」來達到其他級別。 – AMissico

+0

IsVirtualizing = False沒有區別。 – AMissico

+0

項目集合是硬編碼項目。 – AMissico

1

是的,你可以強制一個ItemsControl項目的創建。 訪問ItemContainerGenerator,然後(這是魔法;))將其轉換爲IItemContainerGenerator,因爲接口是顯式實現的。 使用StartAt和GenerateNext可以強制要創建的項目。

請參閱:Why does ItemContainerGenerator return null? 您只需要爲所有項目執行此操作。

+0

我無法修改代碼以便正常工作。你能提供一個例子嗎? – AMissico

+0

這裏你有一個完整的例子如何強制物品創建:http://stackoverflow.com/questions/630124/forcing-wpf-to-create-the-items-in-an-itemscontrol –

+0

太複雜。它不是那麼難。 – AMissico

相關問題