8

I have a custom ControlTemplate for a WPF TabControl that adds Buttons to the left and right hand side of the TabItem header. At the moment this is not a named part as the button commands are bound in the ControlTemplates XAML and do not need to be exposed outside of the ControlTemplate.

This works fine for a button but what if I want to add content to the left (or right) hand side of the TabItemHeaders which can be bound outside of the ControlTemplate so that my TabControl becomes more flexible?

My idea was to subclass the TabControl and have two named parts in the ControlTemplate and expose these as properties of the new control; CustomTabControl.LeftContentArea and CustomTabControl.RightContentArea respectively. Each named part is a ContentPresenter and each ContentPresenters Content property is exposed by the properties named above.

However, when I tried this I was unable to put content into the left and right content areas.

Edit: Just to be clear I have included an image. The red rectangles show where I want to be able to place extra content.

alt text

Update: Below is a screen shot of the progress I have made so far, hopefully this will help explain my problem a bit more.

The screen shot shows my custom Tab Control with two blank tabs and three buttons that are currently on the right hand side of the TabItem header area. The buttons are currently defined in the TabControls custom ControlTemplate I.E. there is a ColumnDefinition within the ControlTemplates Grid which contains a StackPanel that hosts 3 buttons.

alt text

What I am looking for is a way to allow the consumer of the tab control decide what content goes in the area next to the tabs. E.G. the user should be able to do something like this:

<local:CustomTabControl>
    <local:CustomTabControl.RightContentArea>
        <!-- This can be changed to ANY content that the user wants -->
        <StackPanel Orientation="Horizontal">
            <Button Content="Test" />
            <Button Content="Test" />
            <Button Content="Test" />
        </StackPanel>
    </local:CustomTabControl.RightContentArea>

    <!-- TabItems are added as normal -->
    <TabItem Header="Tab One" />
    <TabItem Header="Tab Two" />

</local:CustomTabControl>
Benjamin Gale
  • 12,977
  • 6
  • 62
  • 100

2 Answers2

6

I tried a different (lazy) way, which was to create another grid that occupies the same space as the TabControl, ie both are in Grid.Row=0. I have bound the grid height to the height of the first tab so if the tabs change height the other controls will remain centered. I set MinWidth on the window so the controls dont overlap the tabs.

Paste this code into a new WPF Window...

<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="306" Width="490" MinWidth="300">
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="*" />
        <RowDefinition Height="Auto" />
    </Grid.RowDefinitions>
    <TabControl Grid.Row="0" x:Name="tabControl">
        <TabItem x:Name="tabItem" Header="TabItem" Height="50">
            <Grid Background="#FFE5E5E5"/>
        </TabItem>
        <TabItem Header="TabItem">
            <Grid Background="#FFE5E5E5"/>
        </TabItem>
    </TabControl>

    <Grid Grid.Row="0" Height="{Binding ActualHeight, ElementName=tabItem}" 
       VerticalAlignment="Top" Margin="0,2,0,0">
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" 
                VerticalAlignment="Center" Margin="20,0">
            <TextBlock VerticalAlignment="Center" Margin="10,0" FontSize="16" 
                   Foreground="Red" FontFamily="Calibri">My Text</TextBlock>
            <Button Content="My Button" />
        </StackPanel>
    </Grid>

</Grid>
</Window>

...and you will get this:

enter image description here

TripleAntigen
  • 2,221
  • 1
  • 31
  • 44
3

Depending on how much flexibility you need there are some methods that are suited better than others, i myself try to use DynamicResources if possible because it is normally less troublesome than creating new user-controls.

Here's an example of how to add additional content to the left of the Tab-Header:

<TabControl>

    <TabControl.Resources>
        <DataTemplate x:Key="AugmentedTabItem">
            <StackPanel Orientation="Horizontal">
                <ContentPresenter Content="{DynamicResource ContentLeft}" Margin="0,0,5,0"/>
                <ContentPresenter Content="{Binding}"/>
            </StackPanel>
        </DataTemplate>     
    </TabControl.Resources>

    <TabItem Header="ÜberTab" HeaderTemplate="{StaticResource AugmentedTabItem}">
       <TabItem.Resources>
            <TextBlock x:Key="ContentLeft" Text=">>>" Foreground="Blue"/>           

        </TabItem.Resources>
    </TabItem>      
</TabControl>

Hope that helps, if something is unclear or if this doesn't suffice, drop a comment.

Dai
  • 141,631
  • 28
  • 261
  • 374
H.B.
  • 166,899
  • 29
  • 327
  • 400
  • I'm looking for a way of exposing the property in a custom control so I can bind to it like this in XAML: LeftContentArea="{StaticResource MyPanelWithLotsOfButtonsControl}". The custom content needs to be to the left of the TabItems rather than the left of the header. This does help me with another problem I was having so I will upvote once I have enough rep. Thank you. – Benjamin Gale Jan 16 '11 at 13:31
  • You can bind to those resources too actually. By left of the TabItems, do you mean in the Header area to the left of all the tabs? – H.B. Jan 16 '11 at 13:33
  • Yes. In my custom control template I have added an extra ColumnDefinition so that tabs are offset and there is a space for my extra content to be added. I want to expose a property that allows me to put content into this area. – Benjamin Gale Jan 16 '11 at 13:43
  • What you want is a quite complex extension since you need to override the TabControl's ControlTemplate to accommodate those areas, one problem i encountered was that relative bindings to Horizontal and VerticalAlignment properties did not longer work because the visual tree needed to be changed which somewhat destroyed the layout. – H.B. Jan 16 '11 at 15:53