Changing tab control appearance
-
Tuesday, October 19, 2010 6:25 PM
Hi,
I'm trying to customize the appearance of the WPF tab control. There are several examples I've run across on the web (1, 2) and MSDN's TabControl style and template page. I even dumped out the Tab control's default template by using the 'Dumping the Defaults' routine described in Petzold's MSDN article and then apply that template to a tab control.
All of the above work to customize the appearance of the tab control. However, all suffer from some strange behaviour when the template is applied in VS WPF designer. Here's the XAML skeleton I used for my testing:
<Window x:Class="TabControlTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" Title="MainWindow" Height="350" Width="525"> <Grid> <TabControl Height="100" HorizontalAlignment="Left" Margin="141,109,0,0" Name="tabControl1" VerticalAlignment="Top" Width="200" TabStripPlacement="Top" IsEnabled="True"> <TabControl.Style> <Style TargetType="{x:Type TabControl}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type TabControl}"> <!-- different templates go in here --> </ControlTemplate> </Setter.Value> </Setter> </Style> </TabControl.Style> <TabItem Header="tabItem1" Name="tabItem1"> <Grid /> </TabItem> <TabItem Header="tabItem2"> <Button Content="Button" Height="23" Name="button1" Width="75" /> </TabItem> </TabControl> </Grid> </Window>
So, here are the problems I'm seeing. When I replace the inside of the ControlTemplate above with any control template based on the above, I see two things happening in the WPF designer:
1. If the first tab page is selected, then the Grid within the first Tab item appears in the designer beyond (shifted up, mostly) the borders of the Tab control.
2. If the second tab page is seleted, then when I click on the button within the second tab page, the designer's selection rectangle appears above the visual of the button.
Neither of these problems occur when I don't change the template of the tab control.
Am I applying the template incorrectly? Is this a bug in the VS WPF designer?
Thanks,
Notre
- Moved by Bob_BaoMVP Wednesday, October 20, 2010 10:01 AM WPF designer (From:Windows Presentation Foundation (WPF))
All Replies
-
Wednesday, October 20, 2010 10:00 AM
Hi Notre,
It is a VS WPF Designer related question, I will move it to Visual Studio WPF Designer forum.
On the other hand, I share the default TabControl style/template here (I copied from Blend):<SolidColorBrush x:Key="TabControlNormalBorderBrush" Color="#8C8E94"/> <Style x:Key="TabControlStyle1" TargetType="{x:Type TabControl}"> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.ControlTextBrushKey}}"/> <Setter Property="Padding" Value="4,4,4,4"/> <Setter Property="BorderThickness" Value="1"/> <Setter Property="BorderBrush" Value="{StaticResource TabControlNormalBorderBrush}"/> <Setter Property="Background" Value="#F9F9F9"/> <Setter Property="HorizontalContentAlignment" Value="Center"/> <Setter Property="VerticalContentAlignment" Value="Center"/> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type 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> <TabPanel x:Name="HeaderPanel" Grid.Column="0" IsItemsHost="true" Margin="2,2,2,0" Grid.Row="0" KeyboardNavigation.TabIndex="1" Panel.ZIndex="1"/> <Border x:Name="ContentPanel" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" Grid.Column="0" KeyboardNavigation.DirectionalNavigation="Contained" Grid.Row="1" KeyboardNavigation.TabIndex="2" KeyboardNavigation.TabNavigation="Local"> <ContentPresenter x:Name="PART_SelectedContentHost" ContentSource="SelectedContent" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/> </Border> </Grid> <ControlTemplate.Triggers> <Trigger Property="TabStripPlacement" Value="Bottom"> <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="1"/> <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/> <Setter Property="Height" TargetName="RowDefinition0" Value="*"/> <Setter Property="Height" TargetName="RowDefinition1" Value="Auto"/> <Setter Property="Margin" TargetName="HeaderPanel" Value="2,0,2,2"/> </Trigger> <Trigger Property="TabStripPlacement" Value="Left"> <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/> <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/> <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="0"/> <Setter Property="Grid.Column" TargetName="ContentPanel" Value="1"/> <Setter Property="Width" TargetName="ColumnDefinition0" Value="Auto"/> <Setter Property="Width" TargetName="ColumnDefinition1" Value="*"/> <Setter Property="Height" TargetName="RowDefinition0" Value="*"/> <Setter Property="Height" TargetName="RowDefinition1" Value="0"/> <Setter Property="Margin" TargetName="HeaderPanel" Value="2,2,0,2"/> </Trigger> <Trigger Property="TabStripPlacement" Value="Right"> <Setter Property="Grid.Row" TargetName="HeaderPanel" Value="0"/> <Setter Property="Grid.Row" TargetName="ContentPanel" Value="0"/> <Setter Property="Grid.Column" TargetName="HeaderPanel" Value="1"/> <Setter Property="Grid.Column" TargetName="ContentPanel" Value="0"/> <Setter Property="Width" TargetName="ColumnDefinition0" Value="*"/> <Setter Property="Width" TargetName="ColumnDefinition1" Value="Auto"/> <Setter Property="Height" TargetName="RowDefinition0" Value="*"/> <Setter Property="Height" TargetName="RowDefinition1" Value="0"/> <Setter Property="Margin" TargetName="HeaderPanel" Value="0,2,2,2"/> </Trigger> <Trigger Property="IsEnabled" Value="false"> <Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/> </Trigger> </ControlTemplate.Triggers> </ControlTemplate> </Setter.Value> </Setter> </Style>
TabControl has two blocks, one is for TabItem header, it is a TabPanel which contains the Items another is a ContentPresenter which contains the content of a TabItem. So if you would like to modify a TabControl template, it should have these two block, such as a custom Panel to contain the TabItemHeader and a Content Control to contain the content.
Sincerely,
Bob BaoMSDN Subscriber Support in Forum
If you have any feedback on our support, please contact msdnmg@microsoft.com
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
Are you looking for a typical code sample? Please download all in one code framework !- Proposed As Answer by Miasma Tuesday, November 23, 2010 1:34 AM
-
Wednesday, October 20, 2010 9:25 PM
Hi Bob,
Thanks for sharing the default TabControl template and for planning to move the question to the other forum.
As far as the Tabcontrol having two areas (one for the tab header and one for the content), that is what I thought but it was good to get confirmation I was on the right track.
Thanks,
Notre
-
Friday, February 25, 2011 2:21 AM
Hi,
I have the same problem as described in the post. When adding a <Grid/> under a <TabItem>, the Grid actually docks to the top left of the TabControl and not to the TabItem.
I am using WPF 4, and for testing purposes, I just copied the default TabControl template from Blend and used that as a Style in my project. I see this problem in Visual Studio 2010, but in Blend 4, using the same template, I don't have a problem with the docking - the Grid positions itself underneath the TabItem.
This has puzzled me for days so any help is greatly appreciated.
Thanks
-
Monday, April 16, 2012 12:48 PM
Hi,
In the last couple of days I have just tried to customise a tabcontrol and I too have had this same issue. I thought it was me because I haven't been doing any WPF for long, especially when looking on the web I couldn't see anyone else having these issues --until now this is the only forum I have found other people having this issue, there is plenty out there showing you how to make these customisations but no one afterwards in the pages saying that they are having problems.
I don't have Blend to use but wondered if the code Bob Bao provided is all thats needed? If so I will give it a go once I get home tonight after work. Has anyone else figured it out since? Is this a bug?
Many thanks
-
Monday, April 16, 2012 4:44 PM
I never got the issue I reported resolved. While I'm still interested in a resolution, more pressing things came up so I didn't follow up. I don't think Bob ever moved the question to the VS WPF designer forum. The code Bob provided was not sufficient to resolve the issues I had.
Notre
-
Wednesday, April 18, 2012 9:29 PM
I have been trying a number of things and have managed to get a grid to fill the tabitem's panel...its not a resolution as such but it works. I tried both .NET 3.5 client and .NET 4 to see if it was a problem with .NET 4, but still the same.
All I did is basically have a grid within the grid that sits in the top left of the tabcontrol and for some reason sits nicely. See the code below:
<TabControl Height="Auto" HorizontalAlignment="Stretch" Margin="10" Name="tabControl1" VerticalAlignment="Stretch" Width="Auto"> <TabItem Header="tabItem1" Name="tabItem1"> <Grid> <Grid Height="Auto" HorizontalAlignment="Stretch" Margin="10" Name="grid1" VerticalAlignment="Stretch" Width="Auto"> <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="246,133,0,0" Name="button1" VerticalAlignment="Top" Width="75" /> </Grid> </Grid> </TabItem> <TabItem Header="tabitem2"> <Grid> <Grid Margin="10"> <Button Content="Button" Height="23" HorizontalAlignment="Left" Margin="50,62,0,0" Name="button2" VerticalAlignment="Top" Width="75" /> </Grid> </Grid> </TabItem> <TabItem Header="tabitem3" /> </TabControl> </Grid>I still don't understand why it needs a grid within a grid for it to work. Anyway I thought I would post what I have found, I know its not a proper resolution but it does the trick.
Unless someone else has a fix or resolution I will try this out in a couple of projects and see how it goes.
Cheers!

