Tab Item and Tab Control Border Style - wpf

How do I style the Tab Control Border so that the selected Tab Item does not have a line underneath it?
These are my Tab Control and Tab Item styles so far.
<!-- Tab control styling -->
<Style TargetType="{x:Type TabControl}">
<Setter Property="Padding" Value="10,5,10,5" />
<Setter Property="Margin" Value="3.5" />
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}" />
</Style>
<!-- Tab item styling -->
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid>
<Border
Name="Border"
Background="{DynamicResource {x:Static SystemColors.ControlBrushKey}}"
BorderBrush="Black"
BorderThickness="1,1,1,0"
CornerRadius="3,3,0,0"
MinWidth="120">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="12,2,12,2"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsFocused" Value="True" >
<Setter Property="Background" TargetName="Border" Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}" />
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock FontWeight="Bold" Text="{Binding}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="True" >
<Setter Property="Background" TargetName="Border" Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}" />
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock FontWeight="Bold" Text="{Binding}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="IsSelected" Value="True" >
<Setter Property="Background" TargetName="Border" Value="{DynamicResource {x:Static SystemColors.ControlLightBrushKey}}" />
<Setter Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock FontWeight="Bold" Text="{Binding}"/>
</DataTemplate>
</Setter.Value>
</Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
If I can achieve the look displayed in the screenshot without having to overload the tab item control template then I don't have an issue as the default tab item template doesn't have the line underneath it on the selected tab. I haven't been able to do this so far. Thanks for your help.

The XAML below is how I have overridden the TabControl to solve this problem. The key piece of info is the Margin property of the HeaderPanel. You will see that the bottom margin is -1, which shifts it down just enough to cover up that line.
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid KeyboardNavigation.TabNavigation="Local">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TabPanel x:Name="HeaderPanel"
Grid.Row="0"
Panel.ZIndex="1"
Margin="0,0,4,-1"
IsItemsHost="True"
KeyboardNavigation.TabIndex="1"
Background="Transparent" />
<Border x:Name="Border"
Grid.Row="1"
BorderThickness="1"
KeyboardNavigation.TabNavigation="Local"
KeyboardNavigation.DirectionalNavigation="Contained"
KeyboardNavigation.TabIndex="2">
<Border.Background>
<SolidColorBrush Color="White"/>
</Border.Background>
<Border.BorderBrush>
<SolidColorBrush Color="White"/>
</Border.BorderBrush>
<ContentPresenter x:Name="PART_SelectedContentHost"
Margin="4"
ContentSource="SelectedContent" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

Add property Padding="0,0,0,0" to tab control :-)

Instead of modifying tabcontrol template, you may as well just modify the TabItem template, by adding two lines to cover up the border, and using minus margins for covering up.
(Please take a look at "TopLineCover" and "BottomLineCover" borders.)
<Style TargetType="TabItem" BasedOn="{StaticResource {x:Type TabItem}}">
<Setter Property="Foreground" Value="{DynamicResource VsBrush.WindowText}"/>
<Setter Property="Background" Value="{DynamicResource VsBrush.Window}"/>
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
<Setter Property="VerticalContentAlignment" Value="Stretch"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid SnapsToDevicePixels="true">
<Border x:Name="HeaderBorder" Padding="8,3,8,3" BorderThickness="1,1,1,0"
Background="{DynamicResource {x:Static commonControls:ColorService.JobViewHeaderBrushKey}}"
BorderBrush="{DynamicResource {x:Static commonControls:ColorService.JobViewHeaderBorderBrushKey}}">
<ContentPresenter x:Name="Content" ContentSource="Header"
HorizontalAlignment="{Binding Path=HorizontalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
VerticalAlignment="{Binding Path=VerticalContentAlignment, RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}}"
/>
</Border>
<Border x:Name="TopLineCover" BorderThickness="1,1,1,0" Margin="0,-2,0,0" Height="3" Panel.ZIndex="100"
Background="{DynamicResource VsBrush.Window}" BorderBrush="{DynamicResource {x:Static commonControls:ColorService.JobViewHeaderBorderBrushKey}}"
VerticalAlignment="Top" HorizontalAlignment="Stretch" Visibility="Collapsed"/>
<Border x:Name="BottomLineCover" BorderThickness="0,0,0,3" Margin="1,0,1,-2" Panel.ZIndex="100" BorderBrush="{DynamicResource VsBrush.Window}"
VerticalAlignment="Bottom" HorizontalAlignment="Stretch" Visibility="Collapsed"/>
</Grid>
<ControlTemplate.Triggers>
<MultiTrigger>
<MultiTrigger.Conditions>
<Condition Property="IsMouseOver" Value="True"/>
<Condition Property="IsSelected" Value="False"/>
</MultiTrigger.Conditions>
<Setter Property="Background" TargetName="HeaderBorder" Value="{DynamicResource VsBrush.Window}"/>
</MultiTrigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Background" TargetName="HeaderBorder" Value="{DynamicResource VsBrush.Window}"/>
<Setter Property="Visibility" TargetName="TopLineCover" Value="Visible"/>
<Setter Property="Visibility" TargetName="BottomLineCover" Value="Visible"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

In the past I've accomplished this by making the TabItem extend a little further down then it's allocated, so its actually drawn on top of the border element and hides it
I can't remember how I did it exactly, but I think it was with a negative margin on the bottom of the TabItem

Related

How to change the foreground of the header text of a WPF tabitem onClick?

How can I change only the foreground color of a TabItem header text when it is selected or active without changing the foreground of any item inside that TabItemor anything? I'm new to all this so finding it difficult to figure out where in my TabItemstyling can I implement this little feature and how.
The TabControl style I'm using is:
<Style
x:Key="{x:Type TabControl}"
TargetType="{x:Type TabControl}">
<Setter
Property="BorderThickness"
Value="0" />
<Setter
Property="BorderBrush"
Value="Transparent" />
<Setter
Property="Background"
Value="Transparent" />
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="TabControl">
<Grid>
<Grid.RowDefinitions>
<RowDefinition
Height="Auto" />
<RowDefinition
Height="*" />
</Grid.RowDefinitions>
<Border
BorderThickness="0,0,1,1"
BorderBrush="#D0CEBF"
Grid.Row="1">
<Border
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}">
<Border
Background="{TemplateBinding Background}">
<ContentPresenter
ContentSource="SelectedContent" />
</Border>
</Border>
</Border>
<TabPanel
Grid.Row="0"
IsItemsHost="true"
HorizontalAlignment="Center" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style
TargetType="TabItem">
<Setter
Property="BorderThickness"
Value="0" />
<Setter
Property="BorderBrush"
Value="Transparent" />
<Setter
Property="Background"
Value="Transparent" />
<Setter
Property="VerticalContentAlignment"
Value="Center" />
<Setter
Property="HorizontalContentAlignment"
Value="Center" />
<Setter
Property="Template">
<Setter.Value>
<ControlTemplate
TargetType="{x:Type TabItem}">
<!--In order to click on the blank part of the TabItem can be successfully selected-->
<Border
Background="Transparent">
<Grid>
<Grid
x:Name="g">
<Path
Fill="{TemplateBinding Background}"
Margin="0,0,0,-1"
Data="M 20,40 L 0,40 0,40 C 4,40 10,36 10,30 L 10,10 C 10,0 16,0 20,0 L 155,0 C 165,0 173,0 ,175,6 L175,30 C 175,30 175,38 182,40 Z" />
</Grid>
<Border
BorderThickness="{TemplateBinding BorderThickness}"
Padding="{TemplateBinding Padding}">
<ContentPresenter
ContentSource="Header"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Border>
</Grid>
</Border>
<!--Add ControlTemplate.Triggers to change the background color of the selected TabItem.-->
<ControlTemplate.Triggers>
<Trigger
Property="IsSelected"
Value="false">
<Setter
Property="Visibility"
TargetName="g"
Value="Hidden" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Adding a trigger in your TabItem control template unfortunately sets the foreground color of the TabItem content, too, when the tab is selected, so this does not work.
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Red" />
</Trigger>
However, you could add an implicit TextBlock style (without x:Key) inside the ContentPresenter resources. It will be applied automatically only to TextBlocks inside of its scope, not affecting the TabItem content or even other elements in a custom header template other than TextBlocks.
<ContentPresenter
ContentSource="Header"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" >
<ContentPresenter.Resources>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger
Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type TabItem}}}"
Value="true">
<Setter
Property="Foreground"
Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</ContentPresenter.Resources>
</ContentPresenter>
Alternatively, a specialized solution is to create a header template and put the trigger there. In this case it does not force an overridden header template to apply the foreground to each TextBlock.
<Setter
Property="HeaderTemplate">
<Setter.Value>
<DataTemplate>
<TextBlock Text="{Binding}">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger
Binding="{Binding IsSelected, RelativeSource={RelativeSource AncestorType={x:Type TabItem}}}"
Value="true">
<Setter
Property="Foreground"
Value="Red" />
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</Setter.Value>
</Setter>

Datagrid mouseover header image overlapping

I have image to display when I do mouseover on column header. But imp thing is it should be display below columnheader area.
I am able to create that but's it's overlapping with below cell. Here is image.
Here is my code:
<Style TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="HorizontalContentAlignment" Value="Center" />
<Setter Property="Height" Value="26" />
<Setter Property="Width" Value="126" />
<Setter Property="Foreground" Value="{DynamicResource ContrastWhiteBrush}" />
<Setter Property="Background" Value="{DynamicResource ContentToGreyedOutBrush}" />
<Setter Property="Template" Value="{StaticResource ColumnHeaderControlTemplate}" />
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource GridHeaderMouseOverBrush}" />
</Trigger>
<Trigger Property="prism:DataGridProperties.IsMouseOverGridCellColumnHeader" Value="True">
<Setter Property="Background" Value="{DynamicResource GridHeaderMouseOverBrush}" />
</Trigger>
</Style.Triggers>
<ControlTemplate x:Key="ColumnHeaderControlTemplate" TargetType="{x:Type DataGridColumnHeader}" >
<AdornerDecorator>
<Grid Background="{TemplateBinding Background}" x:Name="dgColumnHeader" Panel.ZIndex="10001">
<ad:Interaction.Behaviors>
<GridColumnHeaderControl:GridAdornerBehavior AdornerTemplate="{StaticResource AdornerDataTemplate}" Panel.ZIndex="19999">
<ad:Interaction.Triggers>
<ad:EventTrigger SourceName="dgColumnHeader" EventName="MouseEnter">
<ad:InvokeCommandAction CommandName="ShowAdornerCommand"/>
</ad:EventTrigger>
<ad:EventTrigger SourceName="dgColumnHeader" EventName="MouseLeave">
<ad:InvokeCommandAction CommandName="HideAdornerCommand"/>
</ad:EventTrigger>
</ad:Interaction.Triggers>
</GridColumnHeaderControl:GridAdornerBehavior>
</ad:Interaction.Behaviors>
<Border x:Name="border" BorderBrush="Black" BorderThickness="0,0,1,1" Grid.ColumnSpan="1">
<Rectangle Width="116" Margin="3,3,3,3" HorizontalAlignment="Center" RadiusX="7" RadiusY="7" x:Name="PART_Rectangle" Fill="{DynamicResource ContentOutofFocusBrush}"></Rectangle>
</Border>
<ContentPresenter x:Name="content" HorizontalAlignment="Center" VerticalAlignment="Center" Content="{TemplateBinding Content}" />
</Grid>
</AdornerDecorator>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="PART_Rectangle" Property="Fill" Value="{DynamicResource ActiveItemBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<DataTemplate x:Key="AdornerDataTemplate">
<Grid HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,13,0,0" Grid.ZIndex="99">
<Button Content="X" Width="28" Height="26" Panel.ZIndex="10002" Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ctrls:RhinoDataGrid}}, Path=RemoveSelectedColumnCommand}">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Foreground" Value="Red"/>
<Setter Property="Background" Value="{DynamicResource GridHeaderMouseOverBrush}"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<Setter Property="FontWeight" Value="Heavy"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid>
<Border Background="{TemplateBinding Background}" CornerRadius="0,0,12,12" BorderThickness="1,0,1,1" BorderBrush="Black">
<ContentPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
Margin="{TemplateBinding Padding}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}" RecognizesAccessKey="True"/>
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Button.Style>
</Button>
</Grid>
</DataTemplate>
Some how my rowheader is working. my row header width is 36 and close button width is 28 with left margin 26. and some how image is no overlapping there with cell
Pls help me to fix.
Thanks
Dee
The height of the header is 26
<Setter Property="Height" Value="26" />
How do you expect it to display an image with a height > 26 ?
In order to show your “Close” button on top of the other control, you have to add “Popup” control and add “Close” button as its child. You can define maximum one child, which can be any UIElement.
You should define Event trigger for DatagridColumnHeader’s mouse over event and set “IsOpen = true” of popup control.
e.g.
<Popup Name="myPopup">
<TextBlock Name="myPopupText"
Background="LightBlue"
Foreground="Blue">
Popup Text
</TextBlock>
</Popup>
You can also set below properties to get the expected result.
AllowsTransparency="True"
Placement="Relative"
PlacementTarget="{Binding ElementName=Border}" /* your control name */
HorizontalOffset="0"
VerticalOffset="60"
PopupAnimation="Fade"

WPF: Refine the look of a grouped ComboBox vs. a grouped DataGrid -sample attached -

just watch this screenshot I made so you see the difference:
I have these requirments to be changed in the ComboBox`s PopUp so it looks like the grouped WPF DataGrid, its only about the Popup-area, do not judge the editable area of the ComboBox or that there is no Header... Important are these things, because I could not change them:
ComboBox:
(Green Line) The alternating
Background of the Item must start at
the beginning
(Red Line) The TextBlocks within the
Border must be aligned Center OR
Right1.
(Blue) The weakly visible horizontal
Border must always stretch to the
right side or take all space2.
to 1.) I have no idea why there is a margin
to 2.) HorizontalAlignment of the TextBlock does not work
to 3.) I can make the stackpanel in the ItemTemplate of the Combobox a read background then you can see very well the red color has a margin somehow on the right and left side. Have no idea how to remove that.
Anyone can help, please?
If you want to see the textbox live just download it here:
http://www.sendspace.com/file/6lmbrh
Its a 30 kb VS2010 .NET 4.0 project.
Here is the XAML for the ComboBox:
<Window x:Class="TestComboGrouped.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="600" Width="200">
<Window.Resources>
<Style x:Key="ComboBoxItemStyle" TargetType="ComboBoxItem">
<Setter Property="Foreground" Value="Red"/>
<Style.Triggers>
<Trigger Property="ComboBox.AlternationIndex" Value="0">
<Setter Property="Background" Value="White"></Setter>
</Trigger>
<Trigger Property="ComboBox.AlternationIndex" Value="1">
<Setter Property="Background" >
<Setter.Value>
<LinearGradientBrush RenderOptions.EdgeMode="Aliased" StartPoint="0.5,0.0" EndPoint="0.5,1.0">
<GradientStop Color="#FFFEFEFF" Offset="0"/>
<GradientStop Color="#FFE4F0FC" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="ComboBoxBorderStyle" TargetType="Border">
<Setter Property="UseLayoutRounding" Value="True" />
<Setter Property="BorderBrush" Value="#FFCEDFF6" />
<Setter Property="BorderThickness" Value="1 0 0 1" />
</Style>
<Style x:Key="ComboBoxStyle" BasedOn="{StaticResource {x:Type ComboBox}}" TargetType="{x:Type ComboBox}">
<Setter Property="ItemContainerStyle" Value="{StaticResource ComboBoxItemStyle}"/>
</Style>
<!-- Grouped CollectionView -->
<CollectionViewSource Source="{Binding WeeklyDateList,IsAsync=False}" x:Key="WeeklyView">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription PropertyName="MonthName"/>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
<StackPanel>
<ComboBox
ItemsSource="{Binding Source={StaticResource ResourceKey=WeeklyView}}"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
Style="{StaticResource ComboBoxStyle}"
AlternationCount="2"
MaxDropDownHeight="300"
Width="Auto"
x:Name="comboBox"
>
<ComboBox.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock
Padding="5,0,0,0"
Background="White"
Foreground="DarkBlue"
FontSize="14"
FontWeight="DemiBold"
Text="{Binding Name}"/>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</ComboBox.GroupStyle>
<ComboBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<Border Style="{StaticResource ComboBoxBorderStyle}">
<TextBlock Width="100" Foreground="Purple" Text="{Binding WeeklyLessonDate, StringFormat='yyyy-MM-dd'}"/>
</Border>
<Border Style="{StaticResource ComboBoxBorderStyle}">
<TextBlock Padding="5,0,5,0" Width="40" Text="{Binding WeekNumber}"/>
</Border>
</StackPanel>
</DataTemplate>
</ComboBox.ItemTemplate>
</ComboBox>
</StackPanel>
</Window>1.2.
UPDATE:
#Meleak thats the updated image it looks very nice thanks to you:
I was just about to put my old 2-"ColumnHeader" in that ComboBox`s Popup top area but I could not find anymore my sample... seems due to changing/trying a lot I have overritten that code :/ I know I did it in the controltemplate above the scrollviewer with a stackpanel or a grid with 2 rowdefinitions. But your code looks now totally different to my default combobox controltemplate I have no idea how to merge both code snippets.
I think that was the code where I put the 2 "column headers", just search for inside the POPUP
<Style x:Key="ComboBoxStyle1" TargetType="{x:Type ComboBox}">
<Setter Property="FocusVisualStyle" Value="{StaticResource ComboBoxFocusVisual}"/>
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.WindowTextBrushKey}}"/>
<Setter Property="Background" Value="{StaticResource ButtonNormalBackground}"/>
<Setter Property="BorderBrush" Value="{StaticResource ButtonNormalBorder}"/>
<Setter Property="BorderThickness" Value="1"/>
<Setter Property="ScrollViewer.HorizontalScrollBarVisibility" Value="Auto"/>
<Setter Property="ScrollViewer.VerticalScrollBarVisibility" Value="Auto"/>
<Setter Property="Padding" Value="4,3"/>
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<Setter Property="ScrollViewer.PanningMode" Value="Both"/>
<Setter Property="Stylus.IsFlicksEnabled" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ComboBox}">
<Grid x:Name="MainGrid" SnapsToDevicePixels="true">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition MinWidth="{DynamicResource {x:Static SystemParameters.VerticalScrollBarWidthKey}}" Width="0"/>
</Grid.ColumnDefinitions>
<Popup x:Name="PART_Popup" AllowsTransparency="true" Grid.ColumnSpan="2" IsOpen="{Binding IsDropDownOpen, RelativeSource={RelativeSource TemplatedParent}}" Margin="1" PopupAnimation="{DynamicResource {x:Static SystemParameters.ComboBoxPopupAnimationKey}}" Placement="Bottom">
<Microsoft_Windows_Themes:SystemDropShadowChrome x:Name="Shdw" Color="Transparent" MaxHeight="{TemplateBinding MaxDropDownHeight}" MinWidth="{Binding ActualWidth, ElementName=MainGrid}">
<Border x:Name="DropDownBorder" BorderBrush="{DynamicResource {x:Static SystemColors.WindowFrameBrushKey}}" BorderThickness="1" Background="{DynamicResource {x:Static SystemColors.WindowBrushKey}}">
// Here should be the column headers, but how merge your code with the ItemsPresenter?
<ScrollViewer x:Name="DropDownScrollViewer">
<Grid RenderOptions.ClearTypeHint="Enabled">
<Canvas HorizontalAlignment="Left" Height="0" VerticalAlignment="Top" Width="0">
<Rectangle x:Name="OpaqueRect" Fill="{Binding Background, ElementName=DropDownBorder}" Height="{Binding ActualHeight, ElementName=DropDownBorder}" Width="{Binding ActualWidth, ElementName=DropDownBorder}"/>
</Canvas>
<ItemsPresenter x:Name="ItemsPresenter" KeyboardNavigation.DirectionalNavigation="Contained" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</Grid>
</ScrollViewer>
</Border>
</Microsoft_Windows_Themes:SystemDropShadowChrome>
</Popup>
<ToggleButton BorderBrush="{TemplateBinding BorderBrush}" Background="{TemplateBinding Background}" Grid.ColumnSpan="2" IsChecked="{Binding IsDropDownOpen, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}" Style="{StaticResource ComboBoxReadonlyToggleButton}"/>
<ContentPresenter ContentTemplate="{TemplateBinding SelectionBoxItemTemplate}" ContentTemplateSelector="{TemplateBinding ItemTemplateSelector}" Content="{TemplateBinding SelectionBoxItem}" ContentStringFormat="{TemplateBinding SelectionBoxItemStringFormat}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" IsHitTestVisible="false" Margin="{TemplateBinding Padding}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="HasDropShadow" SourceName="PART_Popup" Value="true">
<Setter Property="Margin" TargetName="Shdw" Value="0,0,5,5"/>
<Setter Property="Color" TargetName="Shdw" Value="#71000000"/>
</Trigger>
<Trigger Property="HasItems" Value="false">
<Setter Property="Height" TargetName="DropDownBorder" Value="95"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{DynamicResource {x:Static SystemColors.GrayTextBrushKey}}"/>
<Setter Property="Background" Value="#FFF4F4F4"/>
</Trigger>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
<Trigger Property="ScrollViewer.CanContentScroll" SourceName="DropDownScrollViewer" Value="false">
<Setter Property="Canvas.Top" TargetName="OpaqueRect" Value="{Binding VerticalOffset, ElementName=DropDownScrollViewer}"/>
<Setter Property="Canvas.Left" TargetName="OpaqueRect" Value="{Binding HorizontalOffset, ElementName=DropDownScrollViewer}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsEditable" Value="true">
<Setter Property="BorderBrush" Value="{StaticResource TextBoxBorder}"/>
<Setter Property="Background" Value="{DynamicResource {x:Static SystemColors.WindowBrushKey}}"/>
<Setter Property="IsTabStop" Value="false"/>
<Setter Property="Padding" Value="3"/>
<Setter Property="Template" Value="{StaticResource ComboBoxEditableTemplate}"/>
</Trigger>
</Style.Triggers>
</Style>
I think it looks pretty close. You can download my modified version from here
Added a template for ComboBoxItem
<SolidColorBrush x:Key="SelectedBackgroundBrush" Color="#DDD" />
<SolidColorBrush x:Key="DisabledForegroundBrush" Color="#888" />
<Style x:Key="ComboBoxItemStyle" TargetType="ComboBoxItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ComboBoxItem">
<Grid HorizontalAlignment="Stretch"
Margin="-5,0,0,0"
Background="{TemplateBinding Background}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="45"/>
</Grid.ColumnDefinitions>
<Border Name="border1"
BorderThickness="0,0,1,1"
BorderBrush="#FFCEDFF6"
Grid.Column="0">
<TextBlock Foreground="Purple"
HorizontalAlignment="Right"
Margin="0,0,2,0"
Text="{Binding WeeklyLessonDate, StringFormat='yyyy-MM-dd'}"/>
</Border>
<Border Name="border2"
BorderThickness="0,0,1,1"
BorderBrush="#FFCEDFF6"
Grid.Column="1">
<TextBlock HorizontalAlignment="Center"
Text="{Binding WeekNumber}"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsHighlighted" Value="true">
<Setter TargetName="border1" Property="Background" Value="{StaticResource SelectedBackgroundBrush}"/>
<Setter TargetName="border2" Property="Background" Value="{StaticResource SelectedBackgroundBrush}"/>
</Trigger>
<Trigger Property="IsEnabled" Value="false">
<Setter Property="Foreground" Value="{StaticResource DisabledForegroundBrush}"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Setter Property="Foreground" Value="Red"/>
<Style.Triggers>
<Trigger Property="ComboBox.AlternationIndex" Value="0">
<Setter Property="Background" Value="White"></Setter>
</Trigger>
<Trigger Property="ComboBox.AlternationIndex" Value="1">
<Setter Property="Background" >
<Setter.Value>
<LinearGradientBrush RenderOptions.EdgeMode="Aliased" StartPoint="0.5,0.0" EndPoint="0.5,1.0">
<GradientStop Color="#FFFEFEFF" Offset="0"/>
<GradientStop Color="#FFE4F0FC" Offset="1"/>
</LinearGradientBrush>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>

Why is WPF DataGrid showing a class name in the header?

I have created a custom style for my WPF datagrid by overriding its control template - nothing unusual, just copied the original template and modified it. Unfortunately, when the grid is drawn, the fully qualified class name of my ViewModel is showing up in the header (the ViewModel happens to be the DataContext of the UserControl that contains the DataGrid). Using Snoop, I have narrowed down which element in the template is showing this class name:
<DataGridColumnHeadersPresenter
Grid.Column="1"
Name="PART_ColumnHeadersPresenter"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.Column}}"/>
The visual tree for this part looks like this:
PART_ColumnHeadersPresenter (DataGridColumnHeadersPresenter)
(Grid)
headerBorder (DataGridHeaderBorder)
(Border)
(TextBlock)
It is this text block that contains the class name! So the questions are
Why does the Border need a TextBlock?
Why is the TextBlock initialized with the class name of the DataContext?
Is there a property at the DataGrid level that controls the conent of this TextBlock?
P.S. To answer the comment below, I am specifying proper paths for the ItemSource and also for each column:
<DataGrid
ItemsSource="{Binding Path=Orders, Mode=TwoWay}"
AutoGenerateColumns="False"
IsReadOnly="True">
<DataGrid.Columns>
<DataGridTextColumn
Header="Creation Time"
Binding="{Binding Path=CreationTime}"
CellStyle="{StaticResource LeftAlignedCellStyle}"
SortMemberPath="CreationTime">
</DataGridTextColumn>
...
</DataGrid.Columns>
</DataGrid>
I don't see any place where I must bind the TextBlock for the column header border. Don't even know how it makes sense!
Based on Avatar's comment, I am sharing my entire template. See below:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:themes="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Classic">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Brushes.xaml"/>
</ResourceDictionary.MergedDictionaries>
<!-- ColumnHeader Gripper Style -->
<Style x:Key="ColumnHeaderGripperStyle" TargetType="{x:Type Thumb}">
<Setter Property="Width" Value="8"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Cursor" Value="SizeWE"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}">
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- DataGridColumnHeader Style -->
<Style x:Key="DataGridColumnHeaderStyle" TargetType="{x:Type DataGridColumnHeader}">
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="Background" Value="{StaticResource HeaderBackgroundBrush}"/>
<Setter Property="Foreground" Value="{StaticResource HeaderForegroundBrush}"/>
<Setter Property="BorderBrush" Value="{StaticResource HeaderBorderBrush}" />
<Setter Property="BorderThickness" Value="0,1,0,1" />
<Setter Property="FontFamily" Value="Trebuchet MS" />
<Setter Property="FontSize" Value="12" />
<Setter Property="FontWeight" Value="Bold" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridColumnHeader}">
<Grid>
<themes:DataGridHeaderBorder
x:Name="headerBorder"
SortDirection="{TemplateBinding SortDirection}"
IsHovered="{TemplateBinding IsMouseOver}"
IsPressed="{TemplateBinding IsPressed}"
IsClickable="{TemplateBinding CanUserSort}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
Padding ="{TemplateBinding Padding}"
SeparatorVisibility="{TemplateBinding SeparatorVisibility}"
SeparatorBrush="{TemplateBinding SeparatorBrush}">
<Border BorderBrush="{StaticResource HeaderInnerBorderBrush}"
BorderThickness="0,1,0,0">
<TextBlock
Text="{Binding}" Margin="7,0,7,0"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" />
</Border>
</themes:DataGridHeaderBorder>
<Thumb x:Name="PART_LeftHeaderGripper"
HorizontalAlignment="Left"
Style="{StaticResource ColumnHeaderGripperStyle}"/>
<Thumb x:Name="PART_RightHeaderGripper"
HorizontalAlignment="Right"
Style="{StaticResource ColumnHeaderGripperStyle}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="headerBorder" Property="Background"
Value="{StaticResource HeaderHighlightedBackgoundBrush}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="headerBorder" Property="Background"
Value="{StaticResource HeaderPressedBackgroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Right Aligned DataGridColumnHeader Style-->
<Style x:Key="RightAlignedColumnHeaderStyle"
TargetType="{x:Type DataGridColumnHeader}"
BasedOn="{StaticResource DataGridColumnHeaderStyle}">
<Setter Property="HorizontalContentAlignment" Value="Right"/>
</Style>
<!-- Center Aligned DataGridColumnHeader Style-->
<Style x:Key="CenterAlignedColumnHeaderStyle"
TargetType="{x:Type DataGridColumnHeader}"
BasedOn="{StaticResource DataGridColumnHeaderStyle}">
<Setter Property="HorizontalContentAlignment" Value="Center"/>
</Style>
<!-- DataGridRowHeader Gripper -->
<Style x:Key="RowHeaderGripperStyle" TargetType="{x:Type Thumb}">
<Setter Property="Height" Value="8"/>
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Cursor" Value="SizeNS"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border Padding="{TemplateBinding Padding}"
Background="{TemplateBinding Background}"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- DataGridRowHeader Style -->
<Style x:Key="{x:Type DataGridRowHeader}"
TargetType="{x:Type DataGridRowHeader}">
<Setter Property="Background" Value="{StaticResource HeaderBackgroundBrush}" />
<Setter Property="BorderBrush" Value="{StaticResource HeaderBorderBrush}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridRowHeader}">
<Grid>
<themes:DataGridHeaderBorder
x:Name="headerBorder"
IsSelected="{TemplateBinding IsRowSelected}"
IsHovered ="{TemplateBinding IsMouseOver}"
IsPressed="{TemplateBinding IsPressed}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="1,0,1,1"
Padding ="{TemplateBinding Padding}"
Orientation="Horizontal"
SeparatorVisibility="{TemplateBinding SeparatorVisibility}"
SeparatorBrush="{TemplateBinding SeparatorBrush}">
<Border BorderBrush="{StaticResource HeaderInnerBorderBrush}"
BorderThickness="0,1,0,0">
<StackPanel Orientation="Horizontal">
<ContentPresenter
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="Center"/>
<Control
SnapsToDevicePixels="false"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}, Path=(Validation.HasError), Converter={StaticResource bool2VisibilityConverter}}"
Template="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGridRow}}, Path=ValidationErrorTemplate}" />
</StackPanel>
</Border>
</themes:DataGridHeaderBorder>
<Thumb x:Name="PART_TopHeaderGripper"
VerticalAlignment="Top"
Style="{StaticResource RowHeaderGripperStyle}"/>
<Thumb x:Name="PART_BottomHeaderGripper"
VerticalAlignment="Bottom"
Style="{StaticResource RowHeaderGripperStyle}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="headerBorder" Property="Background"
Value="{StaticResource HeaderHighlightedBackgoundBrush}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="headerBorder" Property="Background"
Value="{StaticResource HeaderPressedBackgroundBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- DataGridElement Styles -->
<Style x:Key="DataGridElementStyle" TargetType="{x:Type FrameworkElement}">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="7 0 7 0" />
</Style>
<Style x:Key="LeftAlignedElementStyle" TargetType="{x:Type FrameworkElement}" BasedOn="{StaticResource DataGridElementStyle}">
<Setter Property="HorizontalAlignment" Value="Left" />
</Style>
<Style x:Key="CenterAlignedElementStyle" TargetType="{x:Type FrameworkElement}" BasedOn="{StaticResource DataGridElementStyle}">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
<Style x:Key="RightAlignedElementStyle" TargetType="{x:Type FrameworkElement}" BasedOn="{StaticResource DataGridElementStyle}">
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
<!-- DataGridCell Styles -->
<Style x:Key="DataGridCellStyle" TargetType="{x:Type DataGridCell}">
<!-- Remove blue highlight when cell is selected -->
<Setter Property="Background" Value="Transparent" />
<!-- Don't change text color when cell is selected -->
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=Foreground}"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="LeftAlignedCellStyle" TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource DataGridCellStyle}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter Style="{StaticResource LeftAlignedElementStyle}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Center Aligned DataGridCell Style -->
<Style x:Key="CenterAlignedCellStyle" TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource DataGridCellStyle}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter Style="{StaticResource CenterAlignedElementStyle}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- Right Aligned DataGridCell Style -->
<Style x:Key="RightAlignedCellStyle" TargetType="{x:Type DataGridCell}" BasedOn="{StaticResource DataGridCellStyle}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGridCell}">
<Grid Background="{TemplateBinding Background}">
<ContentPresenter Style="{StaticResource RightAlignedElementStyle}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<!-- SelectAllButton ControlTemplate -->
<ControlTemplate x:Key="SelectAllButtonTemplate" TargetType="{x:Type Button}">
<Grid>
<Rectangle x:Name="Border" SnapsToDevicePixels="True"
Stroke="{StaticResource HeaderBorderBrush}"
Fill="{StaticResource HeaderBackgroundBrush}" />
<Border SnapsToDevicePixels="True" Margin="1,1,1,0"
BorderBrush="White" BorderThickness="0,1,0,0" />
<Polygon x:Name="Arrow"
HorizontalAlignment="Right"
VerticalAlignment="Bottom"
Margin="8,8,3,3"
Opacity="0.15"
Fill="Black"
Stretch="Uniform"
Points="0,10 10,10 10,0" />
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Fill"
Value="{StaticResource HeaderHighlightedBackgoundBrush}" />
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter TargetName="Border" Property="Fill"
Value="{StaticResource HeaderPressedBackgroundBrush}" />
</Trigger>
<Trigger Property="IsEnabled" Value="False">
<Setter TargetName="Arrow" Property="Visibility" Value="Collapsed" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
<!-- DataGrid Style -->
<Style x:Key="{x:Type DataGrid}" TargetType="{x:Type DataGrid}">
<Setter Property="Background" Value="{StaticResource DefaultControlBackgroundBrush}"/>
<Setter Property="Foreground" Value="{StaticResource DefaultControlForegroundBrush}"/>
<!-- Remove border around the grid -->
<Setter Property="BorderBrush" Value="{x:Null}" />
<Setter Property="BorderThickness" Value="1" />
<Setter Property="HorizontalGridLinesBrush" Value="{StaticResource GridLineColorBrush}" />
<Setter Property="VerticalGridLinesBrush" Value="{StaticResource GridLineColorBrush}" />
<Setter Property="AlternatingRowBackground" Value="{StaticResource AlternateRowBackgroundBrush}" />
<Setter Property="ColumnHeaderStyle" Value="{StaticResource DataGridColumnHeaderStyle}"/>
<!-- This is needed to force DG to have a non-default value. Otherwise the DGR.DetailsVisibility cannot have a value of VisibleWhenSelected by default. -->
<Setter Property="RowDetailsVisibilityMode" Value="VisibleWhenSelected" />
<Setter Property="ScrollViewer.CanContentScroll" Value="true"/>
<!-- Turn off row headers by default. -->
<Setter Property="HeadersVisibility" Value="Column" />
<Setter Property="GridLinesVisibility" Value="Horizontal" />
<Setter Property="ColumnHeaderHeight" Value="32" />
<Setter Property="RowHeight" Value="32" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type DataGrid}">
<Border
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True"
Padding="{TemplateBinding Padding}">
<ScrollViewer Focusable="false" Name="DG_ScrollViewer">
<ScrollViewer.Template>
<ControlTemplate TargetType="{x:Type ScrollViewer}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!--Left Column Header Corner -->
<Button
Command="{x:Static DataGrid.SelectAllCommand}"
Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=CellsPanelHorizontalOffset}"
Focusable="false"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.All}}"
Template="{StaticResource SelectAllButtonTemplate}"/>
<!--Column Headers-->
<DataGridColumnHeadersPresenter
Grid.Column="1"
Name="PART_ColumnHeadersPresenter"
Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=HeadersVisibility, Converter={x:Static DataGrid.HeadersVisibilityConverter}, ConverterParameter={x:Static DataGridHeadersVisibility.Column}}"/>
<!--DataGrid content-->
<ScrollContentPresenter x:Name="PART_ScrollContentPresenter" Grid.Row="1" Grid.ColumnSpan="2" CanContentScroll="{TemplateBinding CanContentScroll}" />
<ScrollBar
Grid.Row="0" Grid.RowSpan="2" Grid.Column="2" Name="PART_VerticalScrollBar"
Orientation="Vertical"
Maximum="{TemplateBinding ScrollableHeight}"
ViewportSize="{TemplateBinding ViewportHeight}"
Value="{Binding Path=VerticalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
Visibility="{TemplateBinding ComputedVerticalScrollBarVisibility}"/>
<Grid Grid.Row="2" Grid.Column="1">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}, Path=NonFrozenColumnsViewportHorizontalOffset}"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<ScrollBar
Grid.Column="1"
Name="PART_HorizontalScrollBar"
Orientation="Horizontal"
Maximum="{TemplateBinding ScrollableWidth}"
ViewportSize="{TemplateBinding ViewportWidth}"
Value="{Binding Path=HorizontalOffset, RelativeSource={RelativeSource TemplatedParent}, Mode=OneWay}"
Visibility="{TemplateBinding ComputedHorizontalScrollBarVisibility}"/>
</Grid>
</Grid>
</ControlTemplate>
</ScrollViewer.Template>
<ItemsPresenter SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />
</ScrollViewer>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsGrouping" Value="true">
<Setter Property="ScrollViewer.CanContentScroll" Value="false"/>
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
The default template for DataGridColumnHeadersPresenter looks something like this:
<ControlTemplate TargetType="{x:Type DataGridColumnHeadersPresenter}">
<Grid>
<DataGridColumnHeader IsHitTestVisible="False"
Name="PART_FillerColumnHeader"/>
<ItemsPresenter />
</Grid>
</ControlTemplate>
The ItemsPresenter will create a DataGridColumnHeader for each column, but the template also includes a single DataGridColumnHeader that stretches across the entire grid to act as a background. It has no content, so it normally just draws the border in the appropriate theme.
However, your DataGridColumnHeader template includes a TextBlock instead of a ContentPresenter, so it will render the DataContext as a string whether or not it is also the content. Try using a ContentPresenter instead of a TextBlock:
<Border BorderBrush="{StaticResource HeaderInnerBorderBrush}"
BorderThickness="0,1,0,0">
<ContentPresenter
Margin="7,0,7,0"
SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}" />
</Border>

WPF TabControl Templates + ItemContainerStyle

I am attempting to create a Tab Control Style that basically looks like buttons at the top that are centered and content panel below that displays the tabitem content.
I have am kind of new to templates but what I have so far works very well except one thing. I want to be able to set the default forground color for text elements. Normally I have accomplished this by using the ContentPresenter with dependency elements. So something like this.
<ContentPresenter TextElement.Foreground="White"/>
This basically makes any TextElement Control written by this Presenter to inherit this property.
Now I am trying to do the same thing but it's not working! I believe it has something to do with my style being wrong.
Style:
<Style x:Key="MainMenuTab" TargetType="{x:Type TabControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabControl}">
<Grid KeyboardNavigation.TabNavigation="Local" Width="{TemplateBinding Width}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Tab Headers Panel -->
<Grid Grid.Row="0" Background="{StaticResource Brush_ApplicationTabBackground}">
<TabPanel
Name="HeaderPanel"
Grid.Row="0"
Panel.ZIndex="1"
HorizontalAlignment="Center"
VerticalAlignment="Center"
IsItemsHost="True"
KeyboardNavigation.TabIndex="1"
Background="{StaticResource Brush_ApplicationTabBackground}"
>
</TabPanel>
</Grid>
<!-- Tab Body -->
<Border
Name="Border"
Grid.Row="1"
Background="{StaticResource Brush_ApplicationBackground}"
BorderBrush="Transparent"
BorderThickness="1"
CornerRadius="2"
KeyboardNavigation.TabNavigation="Local"
KeyboardNavigation.DirectionalNavigation="Contained"
KeyboardNavigation.TabIndex="2" >
<ContentPresenter
Name="PART_SelectedContentHost"
Margin="4"
ContentSource="SelectedContent" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
<!-- Each Tab should look like this -->
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style>
<Setter Property="Control.Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid Background="{StaticResource Brush_ApplicationTabBackground}">
<Border Width="50" x:Name="BorderTab" Height="50" Margin="5" BorderThickness="1" ClipToBounds="True" BorderBrush="Transparent" Background="Transparent" CornerRadius="5">
<Rectangle x:Name="BackgroundRec" Fill="Transparent" Stroke="Transparent" Width="50" Height="50" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ContentPresenter Name="TheHeaderContentPresenter" Width="50" Height="50" Margin="5" ContentSource="Header" HorizontalAlignment="Center" VerticalAlignment="Center" TextElement.Foreground="White"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Trigger.Setters>
<Setter TargetName="BorderTab" Property="BorderBrush" Value="{StaticResource Brush_ApplicationTabHighlight}"/>
<Setter TargetName="BorderTab" Property="BorderThickness" Value="3"/>
<Setter TargetName="BackgroundRec" Property="Fill" Value="{StaticResource Brush_ApplicationTabHighlight}"/>
<Setter Property="Panel.ZIndex" Value="1"/>
</Trigger.Setters>
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Trigger.Setters>
<Setter TargetName="BorderTab" Property="BorderBrush" Value="{StaticResource Brush_ApplicationTabBackground}"/>
<Setter TargetName="BorderTab" Property="BorderThickness" Value="0"/>
<Setter TargetName="BackgroundRec" Property="Fill" Value="{StaticResource Brush_ApplicationTabBackground}"/>
</Trigger.Setters>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
In my ContentPresenter under ItemContainerStyle has the TextElement.Foreground="White" property but it will not print white text!
My tabcontrol that uses this style looks like this:
<TabControl Grid.Row="2" Style="{StaticResource MainMenuTab}">
<TabItem>
<TabItem.Header>
<TextBlock VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,5" Text="{x:Static UIStrings:ClientStrings.MainWindow_TabHeader_SingleWaveLength}"></TextBlock>
</TabItem.Header>
<TextBlock>TEST PANEL</TextBlock>
</TabItem>
</TabControl>
I know this is compicated but I would really love this to work.
Solution Found.
Based on HCL's post, I have found a solution. I am experiance the same exact problem I am trying to have the content presenter set the inherited dependence property. instead I simple tell the template to apply the dependance property, that way each tabitem is styled to have this property and therefore sets it for all it's children.
<Setter Property="ItemContainerStyle">
<Setter.Value>
<Style TargetType="TabItem">
<Setter Property="TextElement.Foreground" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid Background="{StaticResource Brush_ApplicationTabBackground}">
<Border Width="50" x:Name="BorderTab" Height="50" Margin="5" BorderThickness="1" ClipToBounds="True" BorderBrush="Transparent" Background="Transparent" CornerRadius="5">
<Rectangle x:Name="BackgroundRec" Fill="Transparent" Stroke="Transparent" Width="50" Height="50" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Border>
<ContentPresenter Name="TheHeaderContentPresenter" Width="50" Height="50" Margin="5" ContentSource="Header" HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Trigger.Setters>
<Setter TargetName="BorderTab" Property="BorderBrush" Value="{StaticResource Brush_ApplicationTabHighlight}"/>
<Setter TargetName="BorderTab" Property="BorderThickness" Value="3"/>
<Setter TargetName="BackgroundRec" Property="Fill" Value="{StaticResource Brush_ApplicationTabHighlight}"/>
<Setter Property="Panel.ZIndex" Value="1"/>
</Trigger.Setters>
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Trigger.Setters>
<Setter TargetName="BorderTab" Property="BorderBrush" Value="{StaticResource Brush_ApplicationTabBackground}"/>
<Setter TargetName="BorderTab" Property="BorderThickness" Value="0"/>
<Setter TargetName="BackgroundRec" Property="Fill" Value="{StaticResource Brush_ApplicationTabBackground}"/>
</Trigger.Setters>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Setter.Value>
</Setter>
All I've really dont is added the line:
<Setter Property="TextElement.Foreground" Value="White"/>
Before the control template! Also I took the white text out of the content presenter because it is useless.
Check this post, it looks to me as it is the same effect:
ContentPresenter within ControlTemplate cannot change attached dependency property

Resources