Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TreeView.ItemContainerGenerator.ContainerFromItem returns null for nonroot items. Workaround?

In the following sample, when I select "String", the title of the window turns to "null". But I must obtain the container of "String". Specifically, I want to do the equivalent of SelectedItem = null (but that property is read only for TreeView, so I'm trying to get to the container to set its IsSelected to false). What to do?

<Window x:Class="WpfApplication1.Window1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Window.Resources>
        <x:Array xmlns="clr-namespace:System;assembly=mscorlib" x:Key="Array" Type="Object">
            <x:ArrayExtension Type="Object">
                <String>String</String>
            </x:ArrayExtension>
        </x:Array>
    </Window.Resources>
    <TreeView ItemsSource="{StaticResource Array}" SelectedItemChanged="Handler">
        <TreeView.ItemTemplate>
            <HierarchicalDataTemplate ItemsSource="{Binding}">
                <TextBlock Text="Array"/>
                <HierarchicalDataTemplate.ItemTemplate>
                    <DataTemplate>
                        <TextBlock Text="{Binding}"/>
                    </DataTemplate>
                </HierarchicalDataTemplate.ItemTemplate>
            </HierarchicalDataTemplate>
        </TreeView.ItemTemplate>
    </TreeView>

namespace WpfApplication1
{
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }

        private void Handler(object sender, EventArgs e)
        {
            var treeView = sender as TreeView;
            var container = treeView.ItemContainerGenerator.ContainerFromItem(treeView.SelectedItem);
            Title = container != null ? container.ToString() : "null";
        }
    }
}
like image 279
CannibalSmith Avatar asked Oct 06 '09 13:10

CannibalSmith


1 Answers

The issue is that each TreeViewItem is itself an ItemsControl so they each manage their own containers for their children.

However, there's a very simple way to do what you want to do: instead of registering to the SelectedItemChanged event, register to the TreeViewItem.Selected event that will bubble up with the OriginalSource set to the selected TreeViewItem.

XAML:

<TreeView ItemsSource="{StaticResource Array}" TreeViewItem.Selected="TreeViewItem_Selected">

Code behind:

private void TreeViewItem_Selected(object sender, RoutedEventArgs e) {
    TreeViewItem container = (TreeViewItem) e.OriginalSource;
    Title = container != null ? container.ToString() : "null";
}
like image 116
Julien Lebosquain Avatar answered Nov 19 '22 14:11

Julien Lebosquain