wpf 在代码中添加项目时将 ItemTemplate 用于 TreeView
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1175039/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using ItemTemplate for a TreeView when adding items in code
提问by Wallstreet Programmer
I'm adding TreeViewItems manually in code behind and would like to use a DataTemplate to display them but can't figure out how to. I'm hoping to do something like this but the items are displayed as empty headers. What am I doing wrong?
我正在后面的代码中手动添加 TreeViewItems,并想使用 DataTemplate 来显示它们,但不知道如何操作。我希望做这样的事情,但项目显示为空标题。我究竟做错了什么?
XAML
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>
Behind code
背后的代码
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; }
}
}
回答by Matt Hamilton
Your ItemTemplate is trying to render a "Name" and "Age" property in TextBlocks, but TreeViewItem doesn't have an "Age" property and you aren't setting its "Name".
您的 ItemTemplate 试图在 TextBlocks 中呈现“Name”和“Age”属性,但 TreeViewItem 没有“Age”属性并且您没有设置其“Name”。
Because you're using an ItemTemplate, there's no need to add TreeViewItems to the tree. Instead, add your Person instances directly:
因为您使用的是 ItemTemplate,所以无需将 TreeViewItems 添加到树中。相反,直接添加您的 Person 实例:
_treeView.Items.Add(new Person { Name = "Sally", Age = 28});
The problem, of course, is that your underlying object ("Person") doesn't have any concept of hierarchy, so there's no simple way to add "Joe" to "Sally". There are a couple of more complex options:
当然,问题在于您的底层对象(“Person”)没有任何层次结构概念,因此没有简单的方法可以将“Joe”添加到“Sally”。有几个更复杂的选项:
You could try handling the TreeView.ItemContainerGenerator.StatusChanged event and wait for the "Sally" item to be generated, then get a handle to it and add Joe directly:
您可以尝试处理 TreeView.ItemContainerGenerator.StatusChanged 事件并等待生成“Sally”项目,然后获取它的句柄并直接添加 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 });
};
}
Or, a better solution, you could introduce the hierarchy concept into your "Person" object and use a HierarchicalDataTemplate to define the TreeView hierarchy:
或者,更好的解决方案是,您可以将层次结构概念引入到“人”对象中,并使用 HierarchicalDataTemplate 来定义 TreeView 层次结构:
XAML:
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; }
}
}
This is a more "data-oriented" way to display your hierarchy and a better approach IMHO.
这是一种更“面向数据”的方式来显示您的层次结构和更好的方法恕我直言。
回答by Dong
It will work if you pull your DataTemplate out of the TreeView and put it into Window.Resources. Like this:
如果您将 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>
Don't forget to add the right namespace before Person.
不要忘记在 Person 之前添加正确的命名空间。