65.9K
CodeProject is changing. Read more.
Home

Custom Tab Style

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (4 votes)

Jun 17, 2009

CPOL

1 min read

viewsIcon

40374

downloadIcon

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:

   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.

   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:

   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:

   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.