2009-07-23 11 views
9

Estoy agregando TreeViewItems manualmente en el código subyacente y me gustaría usar un DataTemplate para mostrarlos pero no puedo encontrar cómo hacerlo. Espero hacer algo como esto, pero los elementos se muestran como encabezados vacíos. ¿Qué estoy haciendo mal?Uso de ItemTemplate para TreeView al agregar elementos en el código

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> 

Detrás de código

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

Respuesta

11

Su ItemTemplate está tratando de hacer un "Nombre" y la propiedad "Edad" en TextBlocks, pero TreeViewItem no tiene una propiedad "Edad" y no estás configurando su "Nombre".

Dado que está utilizando una plantilla de elemento, no es necesario agregar TreeViewItems al árbol. En su lugar, agregue las instancias persona directamente:

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

El problema, por supuesto, es que su objeto subyacente ("Persona") no tiene ningún concepto de jerarquía, así que no hay forma sencilla de añadir "Joe" a "Sally". Hay un par de opciones más complejas:

usted podría tratar de controlar el evento TreeView.ItemContainerGenerator.StatusChanged y esperar a que el elemento "Sally" a generar, a continuación, obtener un identificador para él y añadir directamente Joe:

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

O, una solución mejor, se podría introducir el concepto de jerarquía en su objeto "Persona" y utilizar un HierarchicalDataTemplate para definir la jerarquía 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> 

CÓDIGO:

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

Esta es una forma más "orientado a datos" para mostrar su jerarquía y un mejor enfoque en mi humilde opinión.

+0

Ambas soluciones funcionan. Perdón por tomar tanto tiempo para contactarte. Terminé no usando un árbol al final, sino que implementé un cuadro de lista jerárquico personalizado. –

+1

¡Hurra por Matt! justo lo que necesitaba (la segunda solución) –

0

Funcionará si saca su DataTemplate del TreeView y lo coloca en Window.Resources. De esta manera:

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

No olvide agregar el espacio de nombre correcto antes que Persona.

Cuestiones relacionadas