Search code examples
wpftreeviewitemscontrolitemspanelvirtualizingstackpanel

How to obtain the panel within a treeview (WPF)


How can one obtain the panel that is used within a TreeView? I've read that by default TreeView uses a VirtualizingStackPanel for this. When I look at a TreeView template, all I see is <ItemsPresenter />, which seems to hide the details of what panel is used.

Possible solutions:

1) On the treeview instance ("tv"), from code, do this: tv.ItemsPanel.

The problem is, this does not return a panel, but an ItemsPanelTemplate ("gets or sets the template that defines the panel that controls the layout of the items").

2) Make a TreeView template that explicitly replaces <ItemsPresenter /> with your own ItemsControl.ItemsPanel. I am providing a special template anyways, so this is fine in my scenario. Then give a part name to the panel that you place within that template, and from code you can obtain that part (i.e. the panel). The problem with this? see below.

(I am using a control named VirtualTreeView which is derived from TreeView, as is seen below):

<ControlTemplate x:Key="VirtualTreeViewTemplate" TargetType="{x:Type local:VirtualTreeView}">
    <Border>
        <local:VirtualScrollViewer 
             Style="{StaticResource VirtualScrollViewer}"
             x:Name="PART_VirtualScrollViewer"
                    CanContentScroll="True">
                <!-- instead of: <ItemsPresenter />, use following: -->
                <ItemsControl>
                    <ItemsControl.ItemsPanel>
                        <ItemsPanelTemplate>
                            <StackPanel
                            Name="PART_ItemsStackPanel"
                            IsItemsHost="True" />
                        </ItemsPanelTemplate>
                    </ItemsControl.ItemsPanel>
                </ItemsControl>
        </local:VirtualScrollViewer>
    </Border>
</ControlTemplate>

[I stripped out all clutter here for visibility...]

The problem with this is: this immediately overrides any TreeView layout mechanism. Actually, you just get a blank screen, even when you have TreeViewItems filling the tree. Well, the reason I want to get a hold of the panel is to take some part in the MeaureOverride, but without going into all of that, I certainly do not want to rewrite the book of how to layout a treeview. I.e., doing this the step #2 way seems to invalidate the point of even using a TreeView in the first place.

Sorry if there is some confusion here, thanks for any help you can offer.


Solution

  • There is a class called VisualTreeHelper that allows you to get non-exposed child controls/elements of a control.

    Here is a link to the GetChild method on that class which allows you to enumerate all the children, etc:

    http://msdn.microsoft.com/en-us/library/system.windows.media.visualtreehelper.getchild.aspx