Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why do tab controls reuse View instances when changing tab

I have a WPF project following an MVVM pattern.

I have one control that contains a tab control. The tab control binds to an observable collection. Each item in the observable collection is a view model for a specific tab page to be shown.

The xaml file implementing the tab control uses a data template to select a specific user control to display, depending on the concrete type of the view model in the observable collection.

The strange behavior I observe is, when I change between two tabs of a different type, a new instance of the user control is created. When I change between two tabs of the same type, WPF reuses the same instance of the user control, it just changes the DataContext on the control.

This has some very unfortunate consequences, e.g. when changing between two tabs of the same type, but with different visual state, then the visual state transition animation is displayed, where it should not; the change should be instant. Also some exceptions occur when changing between two tabs of different type.

Can I change this behavior so the tab control will hold one instance of the user control for each tab page, and not "destroy" the controls, when switching to a different tab.

<UserControl.Resources>
    <DataTemplate DataType="{x:Type ViewModels:ConcreteViewModel1}" d:IsDataSource="true">
        <Views:ConcreteView1 />
    </DataTemplate>
    <DataTemplate DataType="{x:Type ViewModels:ConcreteViewModel2}" d:IsDataSource="true">
        <Views:ConcreteView2/>
    </DataTemplate>
    ...
</UserControl.Resources>

<Grid x:Name="ControlTabLayoutRoot">
    <TabControl Grid.Row="0" x:Name="Main_TabControl"
        ItemsSource="{Binding MainTabControl}"
        SelectedIndex="{Binding SelectedIndex}" 
        IsSynchronizedWithCurrentItem="True"
        HorizontalContentAlignment="Stretch" 
        VerticalContentAlignment="Stretch"
        ItemContainerStyle="{DynamicResource CustomTabItemStyle}"
        Style="{DynamicResource CustomTabControl}">
    <TabControl.ItemTemplate>
        <DataTemplate>
            <TextBlock>                 
                <TextBlock.Text>
                  <MultiBinding Converter="{StaticResource tabItemHeaderConverter}">
                      <MultiBinding.Bindings>
                          <Binding/>
                          <Binding Path="ProtocolName"/>
                      </MultiBinding.Bindings>
                  </MultiBinding>
                </TextBlock.Text>
            </TextBlock>
        </DataTemplate>
    </TabControl.ItemTemplate>
    </TabControl>
</Grid>
like image 490
Pete Avatar asked Feb 14 '11 14:02

Pete


1 Answers

A TabControl does recycling virtualization internally. You can find two different approaches to prevent this in this StackOverflow questions:

  • WPF TabControl - how to preserve control state within tab items (MVVM pattern)
like image 113
Rick Sladkey Avatar answered Sep 24 '22 18:09

Rick Sladkey