【发布时间】:2009-04-05 12:15:42
【问题描述】:
为了在 TreeViewItem 中存储一个对象(例如,一个类的实例),我目前将该对象存储在 TreeViewItem 的 Header 中,然后覆盖该类的 ToString 方法,以便它显示正确的字符串标题;然后我在活动期间将对象投射回去。
这是实现这类事情的正确方法,还是有更好、更合适的方法?
【问题讨论】:
为了在 TreeViewItem 中存储一个对象(例如,一个类的实例),我目前将该对象存储在 TreeViewItem 的 Header 中,然后覆盖该类的 ToString 方法,以便它显示正确的字符串标题;然后我在活动期间将对象投射回去。
这是实现这类事情的正确方法,还是有更好、更合适的方法?
【问题讨论】:
“正确”的方法是将object 添加到TreeView(或TreeViewItem's)Items 集合并使用HierarchicalDataTemplate 来控制项目的呈现方式:
Person.cs:
public class Person
{
private readonly ICollection<Person> _children = new ObservableCollection<Person>();
public string Name { get; set; }
public ICollection<Person> Children
{
get
{
return _children;
}
}
}
Window1.xaml.cs:
public Window1()
{
InitializeComponent();
var people = new List<Person>();
var kent = new Person() { Name = "Kent" };
kent.Children.Add(new Person() { Name = "Tempany" });
people.Add(kent);
_treeView.ItemsSource = people;
}
Window1.xaml:
<TreeView x:Name="_treeView">
<TreeView.Resources>
<HierarchicalDataTemplate DataType="{x:Type local:Person}" ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}"/>
</HierarchicalDataTemplate>
</TreeView.Resources>
</TreeView>
【讨论】:
我认为上面的“答案”并没有回答实际问题,实际上原始问题表明问题作者已经对问题有了非常有效的解决方案。但是,提供的“答案”只是显示了如何将子对象附加到 TreeViewItem 以及如何使用自定义方法随后呈现它。虽然这很有用,但此答案并未解决原始问题的实际性质。
在很多情况下,TreeViewItem 需要附加一个不属于 TreeViewItem 的项目列表的外部对象。当用户从 TreeView 中选择 TreeViewItem 时,这有助于访问附加的外部对象以用于特定于应用程序的目的。这个概念与将子对象添加到 TreeViewItem 的想法完全不同。
与问题作者最初实施的解决方案相反,解决此问题的另一种方法是子类化 TreeViewItem 类并添加自定义信息,例如附加对象。这个原理在文章http://msdn.microsoft.com/en-us/library/1330h6a4.aspx中有说明。在实现了这个自定义 TreeViewItem 子类之后,这个子类可以添加到 TreeView 或 TreeViewItem 的 Items 列表中。当用户从 TreeView 中选择项目时,从选择返回的对象将是自定义子类,其中将包含子类定义的任何自定义信息。
使用自定义 TreeViewItem 子类而不是 TreeViewItem 的另一个优点是自定义行为可以由子类实现。例如,要在用户将鼠标悬停在项目上时显示自定义工具提示,子类可以为自己设置一个 ToolTip 对象,代码如下:
ToolTip tip = new ToolTip() { Content = "Tooltip display value" };
ToolTipService.SetToolTip(this, tip);
【讨论】: