2009-07-23 5 views
9

Ich füge TreeViewItems manuell im Code zurück und möchte ein DataTemplate verwenden, um sie anzuzeigen, kann aber nicht herausfinden, wie. Ich hoffe, etwas wie das zu tun, aber die Einzelteile werden als leere Überschriften angezeigt. Was mache ich falsch?Verwenden von ItemTemplate für eine TreeView beim Hinzufügen von Elementen im Code

XAML

<Window x:Class="TreeTest.WindowTree" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="WindowTree" Height="300" Width="300"> 
    <Grid> 
     <TreeView Name="_treeView"> 
      <TreeView.ItemTemplate> 
       <DataTemplate> 
        <StackPanel Orientation="Horizontal"> 
         <TextBlock Text="{Binding Path=Name}" /> 
         <TextBlock Text="{Binding Path=Age}" /> 
        </StackPanel> 
       </DataTemplate> 
      </TreeView.ItemTemplate> 
     </TreeView> 
    </Grid> 
</Window> 

Hinter Code

using System.Windows; 
using System.Windows.Controls; 

namespace TreeTest 
{ 
    public partial class WindowTree : Window 
    { 
     public WindowTree() 
     { 
      InitializeComponent(); 

      TreeViewItem itemBob = new TreeViewItem(); 
      itemBob.DataContext = new Person() { Name = "Bob", Age = 34 }; 

      TreeViewItem itemSally = new TreeViewItem(); 
      itemSally.DataContext = new Person() { Name = "Sally", Age = 28 }; ; 

      TreeViewItem itemJoe = new TreeViewItem(); 
      itemJoe.DataContext = new Person() { Name = "Joe", Age = 15 }; ; 
      itemSally.Items.Add(itemJoe); 

      _treeView.Items.Add(itemBob); 
      _treeView.Items.Add(itemSally); 
     } 
    } 

    public class Person 
    { 
     public string Name { get; set; } 
     public int Age { get; set; } 
    } 
} 

Antwort

11

Ihre ItemTemplate versuchen, einen "Namen" und "Alter" Eigenschaft in Textblöcken zu machen, aber TreeViewItem nicht über ein "Alter" Eigentum und du stellst seinen "Namen" nicht ein.

Da Sie ein ItemTemplate verwenden, müssen Sie TreeViewItems nicht zur Struktur hinzufügen. Stattdessen fügen Sie Ihre Person Instanzen direkt:

_treeView.Items.Add(new Person { Name = "Sally", Age = 28}); 

Das Problem ist natürlich, dass die zugrunde liegendes Objekt („Person“) hat keinen Begriff der Hierarchie, also gibt es keinen einfachen Weg „Joe“ hinzufügen zu "Sally". Es gibt ein paar komplexere Optionen:

Sie könnten versuchen, die TreeView.ItemContainerGenerator.StatusChanged Event-Handling und für die „Sally“ Artikel warten auf erzeugt werden, dann mit einem Griff um es zu bekommen und fügen Joe direkt:

public Window1() 
{ 
    InitializeComponent(); 
    var bob = new Person { Name = "Bob", Age = 34 }; 
    var sally = new Person { Name = "Sally", Age = 28 }; 

    _treeView.Items.Add(bob); 
    _treeView.Items.Add(sally); 

    _treeView.ItemContainerGenerator.StatusChanged += (sender, e) => 
    { 
     if (_treeView.ItemContainerGenerator.Status != GeneratorStatus.ContainersGenerated) 
      return; 

     var sallyItem = _treeView.ItemContainerGenerator.ContainerFromItem(sally) as TreeViewItem; 
     sallyItem.Items.Add(new Person { Name = "Joe", Age = 15 }); 
    }; 
} 

Oder eine bessere Lösung, könnten Sie die Hierarchie-Konzept in die "Person" Objekt vorstellen und eine HierarchicalDataTemplate verwenden, um die TreeView Hierarchie zu definieren:

XAML:

<Window x:Class="TreeTest.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="WindowTree" Height="300" Width="300"> 
    <Grid> 
     <TreeView Name="_treeView"> 
      <TreeView.ItemTemplate> 
       <HierarchicalDataTemplate ItemsSource="{Binding Subordinates}"> 
        <StackPanel Orientation="Horizontal"> 
         <TextBlock Text="{Binding Path=Name}" /> 
         <TextBlock Text="{Binding Path=Age}" /> 
        </StackPanel> 
       </HierarchicalDataTemplate> 
      </TreeView.ItemTemplate> 
     </TreeView> 
    </Grid> 
</Window> 

Code:

using System.Collections.Generic; 
using System.Windows; 

namespace TreeTest 
{ 
    /// <summary> 
    /// Interaction logic for Window1.xaml 
    /// </summary> 
    public partial class Window1 : Window 
    { 
     public Window1() 
     { 
      InitializeComponent(); 
      var bob = new Person { Name = "Bob", Age = 34 }; 
      var sally = new Person { Name = "Sally", Age = 28 }; 

      _treeView.Items.Add(bob); 
      _treeView.Items.Add(sally); 
      sally.Subordinates.Add(new Person { Name = "Joe", Age = 15 }); 
     } 

    } 
    public class Person 
    { 
     public Person() 
     { 
      Subordinates = new List<Person>(); 
     } 

     public string Name { get; set; } 
     public int Age { get; set; } 
     public List<Person> Subordinates { get; private set; } 
    } 
} 

Dies ist ein „datenorientiert“ Weg der Hierarchie und ein besserer Ansatz IMHO anzuzeigen.

+0

Beide Lösungen funktionieren. Entschuldige, dass du so lange gebraucht hast, um dich zu erreichen. Ich habe am Ende keinen Baum verwendet, sondern stattdessen eine benutzerdefinierte hierarchische Listbox implementiert. –

+1

Hurra für Matt! genau das, was ich brauchte (die zweite Lösung) –

0

Es funktioniert, wenn Sie Ihre DataTemplate aus der TreeView ziehen und in Window.Resources einfügen. Wie folgt:

<Window.Resources>  
    <DataTemplate DataType={x:type Person}> 
     <StackPanel Orientation="Horizontal"> 
      <TextBlock Text="{Binding Path=Name}" /> 
      <TextBlock Text="{Binding Path=Age}" /> 
     </StackPanel> 
    </DataTemplate> 
</Window.Resources> 

Vergessen Sie nicht, den richtigen Namespace vor Person hinzuzufügen.