Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WPF: Correctly storing an object in a TreeViewItem

To store an object (say, an instance of a class) in a TreeViewItem, I am currently storing the object in the TreeViewItem's Header and then overriding the ToString method of that class, so that it displays the correct string header; I then cast the object back during an event.


Is this the correct way to achieve this sort of thing, or is there any better, more proper way ?

like image 335
Andreas Grech Avatar asked Apr 05 '09 12:04

Andreas Grech


2 Answers

The "proper" way is to just add the object to the TreeView's (or TreeViewItem's) Items collection and use a HierarchicalDataTemplate to control how the item is rendered:

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>
like image 57
Kent Boogaart Avatar answered Sep 23 '22 01:09

Kent Boogaart


The "answer" above in my view does not answer the actual question, and in fact the original question indicates that the question author already had a very efficient solution to the problem. However, the "answer" provided simply shows how to attach a sub-object to a TreeViewItem and how to subsequently render it using a custom method. While this is useful, this answer does not address the actual nature of the original question.

There are many scenarios where a TreeViewItem needs to have an external object attached which does not belong in the TreeViewItem's Items list. This facilitates access to the attached external object for application-specific purposes when the user selects the TreeViewItem from the TreeView. This concept is entirely different from the idea of adding sub-objects to a TreeViewItem.

An alternate method of solving this problem, as opposed to the solution originally implemented by the question author, is to subclass the TreeViewItem class and add custom information, such as an attached object. This principle is illustrated in the article http://msdn.microsoft.com/en-us/library/1330h6a4.aspx. After implementing this custom TreeViewItem subclass, this subclass may be added to the Items list of either a TreeView or a TreeViewItem. When the user selects the item from the TreeView, the object returned from the selection will be the custom subclass, which will contain whatever custom information the subclass has defined.

An additional advantage of using a custom TreeViewItem subclass instead of a TreeViewItem is that custom behaviors can be implemented by the subclass. For example, to display a custom tooltip when the user hovers the mouse over the item, the subclass may set a ToolTip object for itself with code like:

ToolTip tip = new ToolTip() { Content = "Tooltip display value" };
ToolTipService.SetToolTip(this, tip);
like image 33
Mark Jones Avatar answered Sep 19 '22 01:09

Mark Jones