2009-07-23 15 views
9

Aggiungo TreeViewItem manualmente nel codice dietro e desidero utilizzare un DataTemplate per visualizzarli ma non riesco a capire come. Spero di fare qualcosa di simile ma gli oggetti sono visualizzati come intestazioni vuote. Che cosa sto facendo di sbagliato?Utilizzo di ItemTemplate per TreeView quando si aggiungono elementi nel codice

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> 

Dietro codice

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; } 
    } 
} 

risposta

11

tuo ItemTemplate sta cercando di rendere un "Nome" e la proprietà "Age" in TextBlocks, ma TreeViewItem non ha una proprietà "Age" e non stai impostando il suo "Nome".

Poiché si utilizza un ItemTemplate, non è necessario aggiungere TreeViewItems all'albero. Invece, aggiungere le istanze Persona direttamente:

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

Il problema, naturalmente, è che l'oggetto sottostante ("Persona") non ha alcun concetto di gerarchia, quindi non c'è modo semplice per aggiungere "Joe" a "Sally". Ci sono un paio di opzioni più complesse:

Si potrebbe provare la gestione dell'evento TreeView.ItemContainerGenerator.StatusChanged e attendere che la voce di "Sally" deve essere generato, quindi ottenere una maniglia ad esso e aggiungere Joe direttamente:

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 }); 
    }; 
} 

Oppure, una soluzione migliore, si potrebbe introdurre il concetto della gerarchia nel vostro oggetto "persona" e utilizzare un HierarchicalDataTemplate per definire la gerarchia TreeView:

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> 

CODICE:

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; } 
    } 
} 

Questo è un modo più "data-oriented" per visualizzare la gerarchia e un approccio migliore IMHO.

+0

Entrambe le soluzioni funzionano. Scusa per aver impiegato così tanto tempo a tornare da te. Alla fine non ho usato un albero alla fine, invece ho implementato una listbox gerarchica personalizzata. –

+1

Urrà per Matt! proprio quello di cui avevo bisogno (la seconda soluzione) –

0

Funzionerà se si tira la vostra DataTemplate fuori del controllo TreeView e metterlo in Window.Resources. In questo modo:

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

Non dimenticare di aggiungere lo spazio dei nomi corretto prima di Persona.

Problemi correlati