Click here to Skip to main content
15,867,686 members
Articles / Operating Systems / Windows

Custom Tab Style

Rate me:
Please Sign up or sign in to vote.
4.33/5 (4 votes)
17 Jun 2009CPOL1 min read 39.5K   138   15   10
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)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
I currently hold the following qualifications (amongst others, I also studied Music Technology and Electronics, for my sins)

- MSc (Passed with distinctions), in Information Technology for E-Commerce
- BSc Hons (1st class) in Computer Science & Artificial Intelligence

Both of these at Sussex University UK.

Award(s)

I am lucky enough to have won a few awards for Zany Crazy code articles over the years

  • Microsoft C# MVP 2016
  • Codeproject MVP 2016
  • Microsoft C# MVP 2015
  • Codeproject MVP 2015
  • Microsoft C# MVP 2014
  • Codeproject MVP 2014
  • Microsoft C# MVP 2013
  • Codeproject MVP 2013
  • Microsoft C# MVP 2012
  • Codeproject MVP 2012
  • Microsoft C# MVP 2011
  • Codeproject MVP 2011
  • Microsoft C# MVP 2010
  • Codeproject MVP 2010
  • Microsoft C# MVP 2009
  • Codeproject MVP 2009
  • Microsoft C# MVP 2008
  • Codeproject MVP 2008
  • And numerous codeproject awards which you can see over at my blog

Comments and Discussions

 
GeneralUse as traditional control Pin
Vin5518-Aug-09 10:58
Vin5518-Aug-09 10:58 
GeneralRe: Use as traditional control Pin
Sacha Barber18-Aug-09 20:59
Sacha Barber18-Aug-09 20:59 
When you place a WPF control in a XAML/Page file it looks the same as your standard Winforms Tabs. So if that is the look you are going for just place a TabControl on a Page/XAML file and make sure you do not set either the "Style" or "Template" properties in the XAML and you will have a standard TabControl. This applies to all WPF controls.

Sacha Barber
  • Microsoft Visual C# MVP 2008/2009
  • Codeproject MVP 2008/2009
Your best friend is you.
I'm my best friend too. We share the same views, and hardly ever argue

My Blog : sachabarber.net

GeneralRe: Use as traditional control Pin
Vin5518-Aug-09 22:44
Vin5518-Aug-09 22:44 
GeneralRe: Use as traditional control Pin
Sacha Barber18-Aug-09 23:05
Sacha Barber18-Aug-09 23:05 
GeneralRe: Use as traditional control Pin
Vin5518-Aug-09 23:11
Vin5518-Aug-09 23:11 
GeneralRe: Use as traditional control Pin
Sacha Barber18-Aug-09 23:30
Sacha Barber18-Aug-09 23:30 
GeneralRe: Use as traditional control Pin
Vin5519-Aug-09 0:47
Vin5519-Aug-09 0:47 
GeneralRe: Use as traditional control Pin
Sacha Barber19-Aug-09 4:29
Sacha Barber19-Aug-09 4:29 
GeneralRe: Use as traditional control Pin
Vin5519-Aug-09 6:46
Vin5519-Aug-09 6:46 
GeneralStating the Obvious Pin
sam.hill17-Jun-09 5:01
sam.hill17-Jun-09 5:01 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.