1: <ControlTemplate x:Key="ScrollableTabControlTemplate" TargetType="{x:Type TabControl}">
2: <Grid ClipToBounds="True" SnapsToDevicePixels="True" KeyboardNavigation.TabNavigation="Local">
3: <Grid.ColumnDefinitions>
4: <ColumnDefinition x:Name="ColumnDefinition0"/>
5: <ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
6: </Grid.ColumnDefinitions>
7: <Grid.RowDefinitions>
8: <RowDefinition x:Name="RowDefinition0" Height="Auto"/>
9: <RowDefinition x:Name="RowDefinition1" Height="*"/>
10: </Grid.RowDefinitions>
11: <TabPanel x:Name="HeaderPanel" Margin="2,2,2,0" IsItemsHost="True" Panel.ZIndex="1" Grid.Column="0" Grid.Row="0" KeyboardNavigation.TabIndex="1"/>
12: <Border x:Name="ContentPanel" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Grid.Column="0" Grid.Row="1" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
13: <ContentPresenter x:Name="PART_SelectedContentHost" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding SelectedContent}" ContentSource="SelectedContent" ContentStringFormat="{TemplateBinding SelectedContentStringFormat}" ContentTemplate="{TemplateBinding SelectedContentTemplate}"/>
14: </Border>
15: </Grid>
16: <ControlTemplate.Triggers>
17: <Trigger Property="TabStripPlacement" Value="Bottom">
18: <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/>
19: <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
20: <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
21: <Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/>
22: <Setter Property="Margin" TargetName="HeaderPanel" Value="2,0,2,2"/>
23: </Trigger>
24: <Trigger Property="TabStripPlacement" Value="Left">
25: <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
26: <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
27: <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/>
28: <Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/>
29: <Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/>
30: <Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/>
31: <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
32: <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
33: <Setter Property="Margin" TargetName="HeaderPanel" Value="2,2,0,2"/>
34: </Trigger>
35: <Trigger Property="TabStripPlacement" Value="Right">
36: <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/>
37: <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/>
38: <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/>
39: <Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/>
40: <Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/>
41: <Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/>
42: <Setter Property="Height" TargetName="RowDefinition0" Value="*"/>
43: <Setter Property="Height" TargetName="RowDefinition1" Value="0"/>
44: <Setter Property="Margin" TargetName="HeaderPanel" Value="0,2,2,2"/>
45: </Trigger>
46: <Trigger Property="IsEnabled" Value="False">
47: <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
48: </Trigger>
49: </ControlTemplate.Triggers>
50: </ControlTemplate>
51:
52: I zeroed in on the TabPanel. (Line XX above) This is where the tabs exist. So in order to be able to put them in a single row, I simply wrapped the TabPanel with a ScrollViewer control. I set the vertical scroll bar to disabled and the horizontal scrollbar to Auto.
53:
54: <Grid ClipToBounds="True" SnapsToDevicePixels="True" KeyboardNavigation.TabNavigation="Local">
55: <Grid.ColumnDefinitions>
56: <ColumnDefinition x:Name="ColumnDefinition0"/>
57: <ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
58: </Grid.ColumnDefinitions>
59: <Grid.RowDefinitions>
60: <RowDefinition x:Name="RowDefinition0" Height="Auto"/>
61: <RowDefinition x:Name="RowDefinition1" Height="*"/>
62: </Grid.RowDefinitions>
63: <ScrollViewer VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Auto">
64: <TabPanel x:Name="HeaderPanel" Margin="2,2,2,0" IsItemsHost="True" Panel.ZIndex="1" Grid.Column="0" Grid.Row="0" KeyboardNavigation.TabIndex="1"/>
65: </ScrollViewer>
66: <Border x:Name="ContentPanel" Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Grid.Column="0" Grid.Row="1" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
67: <ContentPresenter x:Name="PART_SelectedContentHost" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" Content="{TemplateBinding SelectedContent}" ContentSource="SelectedContent" ContentStringFormat="{TemplateBinding SelectedContentStringFormat}" ContentTemplate="{TemplateBinding SelectedContentTemplate}"/>
68: </Border>
69: </Grid>
70:
71: Now that will give us a pretty ugly horizontal scrollbar if we run the application. We don’t like ugly so now we have to change the template for that ScrollViewer. Follow the steps that we did for the TabControl Template and create a new resource for the ScrollViewer. I named mine “ScrollViewerTemplate”. Now I once again drilled down into the new template I created by selecting “Edit Resource” from the properties window.
72:
73: <ControlTemplate x:Key="ScrollViewerTemplate" TargetType="{x:Type ScrollViewer}">
74: <Grid x:Name="Grid" Background="{TemplateBinding Background}">
75: <Grid.ColumnDefinitions>
76: <ColumnDefinition Width="*"/>
77: <ColumnDefinition Width="Auto"/>
78: </Grid.ColumnDefinitions>
79: <Grid.RowDefinitions>
80: <RowDefinition Height="*"/>
81: <RowDefinition Height="Auto"/>
82: </Grid.RowDefinitions>
83: <Rectangle x:Name="Corner" Fill="{DynamicResource {x:Static SystemColors.ControlBrushKey}}" Grid.Column="1" Grid.Row="1"/>
84: <ScrollContentPresenter x:Name="PART_ScrollContentPresenter" Margin="{TemplateBinding Padding}" Content="{TemplateBinding Content}" ContentTemplate="{TemplateBinding ContentTemplate}" Grid.Column="0" Grid.Row="0" CanContentScroll="{TemplateBinding CanContentScroll}" CanHorizontallyScroll="False" CanVerticallyScroll="False"/>
85: <ScrollBar x:Name="PART_VerticalScrollBar" Cursor="Arrow" Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}" Grid.Column="1" Grid.Row="0" ViewportSize="{TemplateBinding ViewportHeight}" Maximum="{TemplateBinding ScrollableHeight}" Minimum="0" Value="{Binding VerticalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" AutomationProperties.AutomationId="VerticalScrollBar"/>
86: <ScrollBar x:Name="PART_HorizontalScrollBar" Cursor="Arrow" Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}" Grid.Column="0" Grid.Row="1" Orientation="Horizontal" ViewportSize="{TemplateBinding ViewportWidth}" Maximum="{TemplateBinding ScrollableWidth}" Minimum="0" Value="{Binding HorizontalOffset, Mode=OneWay, RelativeSource={RelativeSource TemplatedParent}}" AutomationProperties.AutomationId="HorizontalScrollBar"/>
87: </Grid>
88: </ControlTemplate>
89: