Search code examples
wpftreeviewtabcontrolonunload

WPF TabControl: Children unloaded when other tab is selected


Is it possible to prevent WPF TabControl from unloading the children of a TabItem when selecting an other tab?

The problem I'm facing is similar to the one described here: WPF TabControl - Preventing Unload on Tab Change?

The solution provided there seems to work only if the TabControl is data bound. It doesn't work if you add TabItems:

<local:TabControlEx>

    <TabItem Header="First Tab">
        <TreeView ItemsSource="{Binding TreeNodes}" Unloaded="treeView_Unloaded">
            <TreeView.Resources>
                <DataTemplate DataType="{x:Type local:NodeViewModel}">
                    <TextBlock Text="{Binding NodeName}" />
                </DataTemplate>
            </TreeView.Resources>

            <TreeView.ItemContainerStyle>
                <Style TargetType="{x:Type TreeViewItem}">
                    <Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
                </Style>
            </TreeView.ItemContainerStyle>
        </TreeView> 
    </TabItem>

    <TabItem Header="Second Tab">
        <TextBlock Name="txText2">Second Text 2</TextBlock>
    </TabItem>

</local:TabControlEx>

When you select "Second Tab", treeView_Unloaded is triggered.

Background: In my real application, one of the TabItems contains a UserControl containing a data bound TreeView: TreeViewItem.IsSelected is bound to a property. Setting the Property bound to IsSelected selects the corresponding TreeViewItem. If the user switches to another tab, the TreeView is unloaded (removed from VisualTree). In that situation, setting IsSelected to true on any node not having a corresponding TreeViewItem causes the TreeView to misbehave - probably because the TreeView does not create a TreeViewItem for the node which should be selected, because the TreeView is not currently part of the visual tree. So what I want to achieve is that I can select any other node by setting IsSelected to true - even if the TreeView is currently on a non-visible tab. Moving the TreeView to some place outside the TabControl seems to resolve the problem - even if it is inside a panel which has visibility collapsed. So, visibility doesn't seem to be the problem, but the fact that the TreeView is not currently part of the visual tree.


Solution

  • The solution presented in the original question works if you override the control template based on the default control template of TabControl: - Remove ContentPresenter - Add a Grid named PART_ItemsHolder.

    No more Unloaded events - no more trouble with the TreeView when it is on a non-selected TabItem.