Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TabControl with single line TabPanel and Overflow Panel

Tags:

wpf

tabcontrol

I want to alter the functionality of the WPF TabControl to only spawn one line, and create a Overflow Popup for each further item (Like the ToolBar / ToolBarOverflowPanel). The same way tabs are shown in VisualStudio at the moment.

This is what i got:

<Style TargetType="TabControl">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="TabControl">
                <Grid KeyboardNavigation.TabNavigation="Local">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto" />
                        <RowDefinition Height="*" />
                    </Grid.RowDefinitions>
                    <controls:OneLineTabPanel x:Name="HeaderPanel"
                                              Grid.Row="0"
                                              Panel.ZIndex="1"
                                              Margin="0"
                                              KeyboardNavigation.TabIndex="1"
                                              Background="Transparent">
                    </controls:OneLineTabPanel>
                 ......

I did now try to alter the TabPanel (which is used to display the headers), but i can't change its template (as it derives from TabPanel). So I try to derive from some other control instead, but then i can not see any items at all.

How can i get my own ItemsControl to work with the TabControl?

like image 458
quadroid Avatar asked Feb 05 '16 08:02

quadroid


1 Answers

You need to override the whole template of TabControl.
Fortunately, it's easy to extract the copy of template using Visual Studio (right click in Document Outline window on TabControl element -> Edit Template -> Edit Copy).

In default TabControl template HeaderPanel is defined in the following way:

<TabPanel x:Name="HeaderPanel" Grid.Column="0" IsItemsHost="true" Margin="2,2,2,0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/>

The main idea is to bind TabControl.Items not to the Panel control by setting IsItemsHost="true", but to completely another control type. For example, to bind to the ToolBar, which has out of the box overflow button feature:

<ToolBar x:Name="HeaderPanel" ItemsSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Items}"/>

Here is a full example of TabControl template with ToolBar as a header panel:

<TabControl>
    <TabControl.Template>
        <ControlTemplate TargetType="{x:Type TabControl}">
            <Grid ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition x:Name="ColumnDefinition0"/>
                    <ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition x:Name="RowDefinition0" Height="Auto"/>
                    <RowDefinition x:Name="RowDefinition1" Height="*"/>
                </Grid.RowDefinitions>

                <!--this will do the trick!!!-->
                <ToolBar x:Name="HeaderPanel" ItemsSource="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Items}"/>

                <Border x:Name="ContentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
                    <ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
                </Border>
            </Grid>
            <ControlTemplate.Triggers>
                <Trigger Property="TabStripPlacement" Value="Bottom">
                    <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/>
                    <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                    <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                    <Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/>
                    <Setter Property="Margin" TargetName="HeaderPanel" Value="2,0,2,2"/>
                </Trigger>
                <Trigger Property="TabStripPlacement" Value="Left">
                    <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
                    <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                    <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/>
                    <Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/>
                    <Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/>
                    <Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/>
                    <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                    <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
                    <Setter Property="Margin" TargetName="HeaderPanel" Value="2,2,0,2"/>
                </Trigger>
                <Trigger Property="TabStripPlacement" Value="Right">
                    <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
                    <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
                    <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/>
                    <Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/>
                    <Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/>
                    <Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/>
                    <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
                    <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
                    <Setter Property="Margin" TargetName="HeaderPanel" Value="0,2,2,2"/>
                </Trigger>
                <Trigger Property="IsEnabled" Value="false">
                    <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
                </Trigger>
            </ControlTemplate.Triggers>
        </ControlTemplate>
    </TabControl.Template>
</TabControl>
like image 182
nicolas2008 Avatar answered Oct 31 '22 18:10

nicolas2008