Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / operating-systems / Windows

Custom Tab Style

4.33/5 (4 votes)
17 Jun 2009CPOL1 min read 40.4K   138  
Custom Tab Style

A little while ago, I mentioned about how important I thought it was to create a brand, and I showed you that you can create some interesting looking controls by Templating/Styling the standard System.Windows controls to create a brand.

I also showed you a ScrollViewer and a Tab control which I had altered. I have since then decided there is no harm in sharing the TabControl code that I created.

So in this post, we will discuss what you need to do to change a standard TabControl from...

37335/image-thumb.png

...into the following slightly funkier TabControl.

37335/image-thumb1.png

As one would expect, it's all about the Templates and Styles applied.

The first thing to understand is how the TabControl is made, it's actually made of a Grid with 2 rows by default, which is something like this:

37335/rows-thumb.jpg

So we can alter this, by changing the RowDefinition to be ColumnDefinition, which will give us something like:

37335/cols-thumb.jpg

This is done with the following XAML:

XML
 1:  <Style x:Key="tab"  TargetType="{x:Type TabControl}">
 2:   <Setter Property="Template">
 3:     <Setter.Value>
 4:       <ControlTemplate TargetType="{x:Type TabControl}">
 5:         <Grid>
 6:           <Grid.ColumnDefinitions>
 7:             <ColumnDefinition Width="auto"/>
 8:             <ColumnDefinition Width="*"/>
 9:           </Grid.ColumnDefinitions>
10:           <StackPanel Orientation="Vertical"
11:              Background="{TemplateBinding Background}"
12:              Grid.Column="0&#8243;
13:              Panel.ZIndex="1&#8243;
14:              IsItemsHost="True"/>
15:           <Border
16:              Grid.Column="1&#8243;
17:              BorderBrush="Black"
18:              BorderThickness="0&#8243;
19:              Background="{TemplateBinding Background}"
20:              CornerRadius="0&#8243;>
21:              <ContentPresenter
22:                ContentSource="SelectedContent" />
23:           </Border>
24:         </Grid>
25:       </ControlTemplate>
26:     </Setter.Value>
27:   </Setter>
28:  </Style>

So that’s that part. The next thing to understand is the TabItem. This is easily achieved by a little Style to replace the standard TabItem look and feel. This is what creates the individual TabItems with the arrows and disabled state.

XML
 1:  <Style TargetType="{x:Type TabItem}">
 2:   <Setter Property="FocusVisualStyle" Value="{x:Null}"/>
 3:   <Setter Property="Template">
 4:     <Setter.Value>
 5:       <ControlTemplate TargetType="{x:Type TabItem}">
 6:          <Grid>
 7:           <Border
 8:              Name="Border"
 9:              Margin="4&#8243;
10:              BorderBrush="Transparent"
11:              BorderThickness="0&#8243;
12:              CornerRadius="0&#8243; >
13:              <StackPanel Orientation="Horizontal">
14:
15:              <Polygon x:Name="Arrow"
16:                       HorizontalAlignment="Left"
17:                       VerticalAlignment="Center" Margin="4&#8243;
18:                       Width="14&#8243; Height="14&#8243;
19:                       Fill="{TemplateBinding Foreground}"
20:                       Visibility="Hidden">
21:                  <Polygon.Points>
22:                      <Point X="0&#8243; Y="0&#8243; />
23:                      <Point X="0&#8243; Y="14&#8243; />
24:                      <Point X="14&#8243; Y="7&#8243; />
25:                  </Polygon.Points>
26:              </Polygon>
27:
28:              <!– Header placeholder–>
29:              <ContentPresenter x:Name="ContentSite"
30:                    VerticalAlignment="Center"
31:                    HorizontalAlignment="Left"
32:                    ContentSource="Header"
33:                    Margin="4&#8243;
34:                    RecognizesAccessKey="True"/>
35:              </StackPanel>
36:            </Border>
37:          </Grid>
38:          <ControlTemplate.Triggers>
39:              <Trigger Property="IsSelected"
40:                       Value="True">
41:                  <Setter Property="Panel.ZIndex"
42:                          Value="100&#8243; />
43:                  <Setter TargetName="Border"
44:                          Property="Background"
45:                          Value="Transparent" />
46:                  <Setter TargetName="Arrow"
47:                          Property="Visibility"
48:                          Value="Visible" />
49:              </Trigger>
50:              <Trigger Property="IsEnabled"
51:                       Value="False">
52:                  <Setter TargetName="Arrow"
53:                          Property="Fill"
54:                          Value="{StaticResource Disabled}" />
55:              </Trigger>
56:          </ControlTemplate.Triggers>
57:        </ControlTemplate>
58:     </Setter.Value>
59:   </Setter>
60:  </Style>

And lastly, we need to change the actual TabItem.Header DataTemplate to respect the disabled state. This is done as follows:

XML
 1:  <DataTemplate x:Key="tabHeader">
 2:      <Label x:Name="lbl" Margin="0&#8243; Content="{Binding}"
 3:         Foreground="{Binding RelativeSource={RelativeSource
 4:         Mode=FindAncestor, AncestorType={x:Type TabItem},
 5:         AncestorLevel=1}, Path=Foreground}"
 6:         VerticalAlignment="Center" />
 7:      <DataTemplate.Triggers>
 8:          <Trigger Property="IsEnabled" Value="False">
 9:              <Setter TargetName="lbl"
10:                      Property="Foreground"
11:                      Value="{StaticResource Disabled}" />
12:          </Trigger>
13:      </DataTemplate.Triggers>
14:  </DataTemplate>

So that’s it, all we need to do now is apply these Styles/Templates to a TabControl like so:

XML
 1:  <TabControl Style="{StaticResource tab}"
 2:              Background="White" Foreground="Orange">
 3:      <TabItem Header="Item1 is here"
 4:               HeaderTemplate="{StaticResource tabHeader}"
 5:               Foreground="Orange" IsEnabled="False" >
 6:          <Button Content="Btn1&#8243; Margin="5&#8243;/>
 7:      </TabItem>
 8:      <TabItem Header="Item2&#8243;
 9:               HeaderTemplate="{StaticResource tabHeader}"
10:               Foreground="Orange" >
11:          <ScrollViewer >
12:              <Canvas x:Name="canv" Width="1200&#8243; Height="1200&#8243;>
13:              </Canvas>
14:          </ScrollViewer>
15:      </TabItem>
16:      <TabItem Header="Item3&#8243;
17:               HeaderTemplate="{StaticResource tabHeader}"
18:               Foreground="Orange" >
19:          <Button Content="Btn3&#8243; Margin="5&#8243;/>
20:      </TabItem>
21:      <TabItem Header="Item4&#8243;
22:               HeaderTemplate="{StaticResource tabHeader}"
23:               Foreground="Orange" >
24:          <Button Content="Btn4&#8243; Margin="5&#8243;/>
25:      </TabItem>
26:  </TabControl>

And there you have it.

Here is a small demo project, should you wish to try it yourself.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)