13

Is there an easy way to position another control (i.e. a button) inline and to the right of tab headers in WPF?

In the web, I would use a float or absolute positioning to accomplish this.

The red line in this picture is what I am trying to get to: A control alongside of WPF Tabs
(source: jonkragh.com)

Thanks! Jon

Glorfindel
  • 21,988
  • 13
  • 81
  • 109
Jon Kragh
  • 4,529
  • 5
  • 26
  • 26
  • 12
    +1 for the most excellent sketch artwork ;) – Steffen Opel Sep 16 '09 at 08:07
  • Thanks Steffen! Created with a Wacom Tablet and OneNote! – Jon Kragh Sep 16 '09 at 17:36
  • Interesting - I'm using the most excellent OneNote daily and intensely too, but the one thing I haven't managed to try for years is adding a tablet to this toolchain, although OneNote is really asking for pen input to further expand the already impressive feature set without one - your comment might finally trigger this now, thanks :) – Steffen Opel Sep 24 '09 at 11:46
  • 1
    The image resource is unavailable – Athafoud Dec 03 '15 at 09:39

2 Answers2

9

The robust way to do this is to re-template the TabControl as I did for the close button in my ActiveAwareCommand sample:

<ControlTemplate x:Key="TabControlTemplate" TargetType="TabControl">
    <Grid ClipToBounds="true" SnapsToDevicePixels="true" KeyboardNavigation.TabNavigation="Local">
        <Grid.ColumnDefinitions>
            <ColumnDefinition x:Name="ColumnDefinition0"/>
            <ColumnDefinition x:Name="ColumnDefinition1" Width="0"/>
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition x:Name="RowDefinition0" Height="Auto"/>
            <RowDefinition x:Name="RowDefinition1" Height="*"/>
        </Grid.RowDefinitions>
        <Grid Panel.ZIndex="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="*"/>
                <ColumnDefinition Width="Auto"/>
            </Grid.ColumnDefinitions>
            <TabPanel Margin="2,2,2,0" x:Name="HeaderPanel" IsItemsHost="true" KeyboardNavigation.TabIndex="1"/>
            <Button Grid.Column="1" Command="{Binding DataContext.CloseCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}" Style="{StaticResource {x:Static ToolBar.ButtonStyleKey}}">X</Button>
        </Grid>
        <Border x:Name="ContentPanel" Grid.Column="0" Grid.Row="1" BorderBrush="#D0CEBF" BorderThickness="0,0,1,1" KeyboardNavigation.DirectionalNavigation="Contained" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local">
            <Border BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
                <Border Background="{TemplateBinding Background}">
                    <Grid x:Name="PART_ItemsHolder"/>
                </Border>
            </Border>
        </Border>
    </Grid>
</ControlTemplate>

Notice how the TabPanel and Button can never overlap. Result:

alt text

Community
  • 1
  • 1
Kent Boogaart
  • 175,602
  • 35
  • 392
  • 393
  • 1
    Thanks! This pointed me in the right direction. I ended up copying the default style/template for tabs (by using Blend) and then made my style/template such that the add tab button is always next to the last tab. I can post that code if anyone is interested. – Jon Kragh Sep 15 '09 at 17:29
  • I am trying to adjust this template to silverlight4 and it is not as straight forward as it might look like. Do you have time to create a Silverlight version of this template please? :) – Houman Jan 28 '11 at 15:09
1

Similar to how you would do it on the web, you can just put the tab control and floating control inside a Grid and set the margins of the floating control to get it in the right spot. You could also use a Canvas element to contain the Grid and floating control and set the Canvas.Left and Canvas.Top.

You might need to dynamically measure the width of each tab, if the tabs are not determined at compile time.

MKing
  • 518
  • 1
  • 4
  • 18