2009-07-23 21 views
9

Dodaję TreeViewItems ręcznie w kodzie z tyłu i chciałbym użyć DataTemplate, aby je wyświetlić, ale nie mogę dowiedzieć się, jak to zrobić. Mam nadzieję, że zrobię coś takiego, ale elementy są wyświetlane jako puste nagłówki. Co ja robię źle?Korzystanie z ItemTemplate dla TreeView podczas dodawania elementów w kodzie

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> 

Za kodem

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

Odpowiedz

11

Twój ItemTemplate próbuje uczynić "nazwa" i "wiek" nieruchomość w TextBlocks, ale TreeViewItem nie ma "wiek" własność i nie ustawiasz jego "Nazwy".

Ponieważ używasz ItemTemplate, nie ma potrzeby dodawania TreeViewItems do drzewa. Zamiast dodawać instancje osoba bezpośrednio:

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

Problem, oczywiście, jest to, że bazowy obiekt („Osoba”) nie mają żadnego pojęcia hierarchii, nie ma więc prosty sposób na dodanie „Joe” do "Sally". Istnieje kilka bardziej skomplikowanych opcji:

można spróbować obsługi zdarzeń TreeView.ItemContainerGenerator.StatusChanged i czekać na „Sally” elementu mają zostać wygenerowane, a następnie uzyskać uchwyt do niego i dodać Joe bezpośrednio:

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

Albo, lepszym rozwiązaniem, można wprowadzić do swojej hierarchii pojęcie „osoba” obiekt i użyć HierarchicalDataTemplate zdefiniowanie hierarchii 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> 

KOD:

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

Jest to bardziej sposób „Dane zorientowanych”, aby wyświetlić hierarchię i lepszym podejściem IMHO.

+0

Oba rozwiązania działają. Przepraszam, że tak długo wróciłem do ciebie. W końcu nie używałem drzewa, zamiast tego zaimplementowałem niestandardowy hierarchiczny listbox. –

+1

Hurra dla Matta! właśnie to, czego potrzebowałem (drugie rozwiązanie) –

0

Będzie działać, jeśli wyciągniesz DataTemplate z widoku TreeView i umieścisz go w oknie. Źródła. W ten sposób:

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

Nie zapomnij dodać właściwej przestrzeni nazw przed osobą.