在代码中添加项目时使用ItemTemplate添加项目
问题描述:
我在后面的代码中手动添加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; }
}
}
答
你的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; }
}
}
这是一个更加“面向数据”的方式来显示您的层次和更好的方法恕我直言。
答
如果您将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之前添加正确的名称空间。
这两个解决方案的工作。对不起,花了这么久回到你身边。我最终没有使用树,而是实现了一个自定义的分层列表框。 – 2009-12-01 23:51:09