2009-07-23 138 views
9

我在後面的代碼中手動添加TreeViewItems並希望使用DataTemplate來顯示它們,但無法弄清楚如何操作。我希望做這樣的事情,但項目顯示爲空頭。我究竟做錯了什麼?在代碼中添加項目時使用ItemTemplate添加項目

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> 

背後代碼

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

回答

11

你的ItemTemplate試圖呈現一個 「名稱」,並在的TextBlocks 「年齡」 屬性,但樹型視圖沒有一個 「年齡」 屬性而你並沒有設定其「名稱」。

因爲您使用的是ItemTemplate,所以不需要將TreeViewItems添加到樹中。相反,直接添加你的個人情況:

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

的問題,當然,那是你潛在的對象(「人」)不具有層次結構的任何概念,所以沒有簡單的方法來添加「喬」到「莎莉」。有一對夫婦的較爲複雜的選項:

你可以嘗試處理TreeView.ItemContainerGenerator.StatusChanged事件,等待要生成的「莎莉」項,然後得到它的句柄,並直接添加喬:

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

或者,更好的解決方案,你可以引入層次概念到你的「人」的對象,並使用HierarchicalDataTemplate定義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> 

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

這是一個更加「面向數據」的方式來顯示您的層次和更好的方法恕我直言。

+0

這兩個解決方案的工作。對不起,花了這麼久回到你身邊。我最終沒有使用樹,而是實現了一個自定義的分層列表框。 – 2009-12-01 23:51:09

0

如果您將DataTemplate從TreeView拖出並放入Window.Resources,它將起作用。像這樣:

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

不要忘記在Person之前添加正確的名稱空間。