Set background of parent based on Content Control's content - wpf

I have this tabitem (default style) template where the tab item's background is set to a fixed colour.
<Style x:Key="tbitem" TargetType="{x:Type TabItem}">
<Setter Property="Focusable" Value="True"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="Continue"/>
<Setter Property="KeyboardNavigation.DirectionalNavigation" Value="Continue"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Border Name="Border" BorderBrush="Transparent" BorderThickness="0" CornerRadius="0" Margin="0" Background="Transparent" >
<DockPanel>
<Label x:Name="TabLabel" DockPanel.Dock="Left" Foreground="White" FontWeight="ExtraBold" FontFamily="Segoe UI" FontSize="14" >
<ContentPresenter HorizontalAlignment="Stretch" VerticalAlignment="Stretch" x:Name="ContentSite" RecognizesAccessKey="True" ContentSource="Header" />
</Label>
<Button Name="PART_BTNCLOSE" DockPanel.Dock="Right" Style="{StaticResource CloseButtonStyle}" Command="USD:ActionCommands.CloseSessionTab"/>
</DockPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Panel.ZIndex" Value="100"/>
<Setter TargetName="Border" Property="BorderBrush" Value="Green"/>
<Setter TargetName="Border" Property="Background" Value="Green"/>
<Setter TargetName="Border" Property="Margin" Value="2,0,0,0"/>
<Setter TargetName="PART_BTNCLOSE" Property="Visibility" Value="{Binding CloseButtonVisibility}"/>
<Setter Property="KeyboardNavigation.TabNavigation" Value="Continue"/>
<Setter Property="KeyboardNavigation.DirectionalNavigation" Value="Continue"/>
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="TabLabel" Property="Foreground" Value="#666666"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
And my actual tabitem contains a textblock to display the tab header
<TabItem Style="{StaticResource SessionTabs}" >
<TabItem.Header>
<TextBlock Text="Tab 1" >
</TextBlock>
</TabItem.Header>
</TabItem>
All working good so far. The problem is.. yet times I have to change one of my tab colour based on some conditions and that If I'm doing it to my textblock then the look and feel is quite odd.
Is there any way I can set my parent's border background to match my textblock's background? or somehow trigger/update ancestor's background from the child?

Set Label padding to 0 and change TabItemHeader like so:
<TabItem.Header>
<Grid Background="Red" Margin="0 0 -10 0">
<TextBlock Margin="5 5 15 5" Text="Tab 1"/>
</Grid>
</TabItem.Header>
-10 is your button width and 15 is (5 + button.Width)

Related

Disable border and background change on TabItem selected wpf

In my WPF document I have this:
<Window.Resources>
<Style x:Key="SidebarTab" TargetType="TabItem">
<Setter Property="Foreground" Value="#303030"></Setter>
<Setter Property="BorderBrush" Value="Transparent"></Setter>
<Setter Property="BorderThickness" Value="0"></Setter>
<Setter Property="Background" Value="#151515"></Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="{StaticResource PrimaryHueMidBrush}"></Setter>
<Setter Property="BorderBrush" Value="Transparent"></Setter>
<Setter Property="BorderThickness" Value="0"></Setter>
<Setter Property="Background" Value="#151515"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</Window.Resources>
<Border Background="#151515" CornerRadius="20">
<Grid Margin="23,47,0,0">
<TabControl TabStripPlacement="Left" Style="{DynamicResource SidebarTabControl}">
<TabItem Style="{DynamicResource SidebarTab}">
<TabItem.Header>
<materialDesign:PackIcon Kind="EmoticonLol" VerticalAlignment="Center" HorizontalAlignment="Left"/>
</TabItem.Header>
</TabItem>
<TabItem Style="{DynamicResource SidebarTab}">
<TabItem.Header>
<materialDesign:PackIcon Kind="EmoticonLol" VerticalAlignment="Center" HorizontalAlignment="Left"/>
</TabItem.Header>
</TabItem>
<TabItem Style="{DynamicResource SidebarTab}">
<TabItem.Header>
<materialDesign:PackIcon Kind="EmoticonLol" VerticalAlignment="Center" HorizontalAlignment="Left"/>
</TabItem.Header>
</TabItem>
<TabItem Style="{DynamicResource SidebarTab}">
<TabItem.Header>
<materialDesign:PackIcon Kind="EmoticonLol" VerticalAlignment="Center" HorizontalAlignment="Left"/>
</TabItem.Header>
</TabItem>
<TabItem Style="{DynamicResource SidebarTab}">
<TabItem.Header>
<materialDesign:PackIcon Kind="EmoticonLol" VerticalAlignment="Center" HorizontalAlignment="Left"/>
</TabItem.Header>
</TabItem>
</TabControl>
</Grid>
</Border>
And it looks like this:
I get the desired effect of the icon changing color on the TabItem, but the Background and BorderBrush (as well as BorderThickness) are still being changed to kind of "link up" to the content inside the header and this is what I want to remove:
I added the things inside the style like so:
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="{StaticResource PrimaryHueMidBrush}"></Setter>
<Setter Property="BorderBrush" Value="Transparent"></Setter>
<Setter Property="BorderThickness" Value="0"></Setter>
<Setter Property="Background" Value="#151515"></Setter>
</Trigger>
</Style.Triggers>
But it still doesn't work. Does anyone have any suggestions on how to do this?
I tried with your styles and I am also able to get the border. The reason for this is actually the default Template of TabItem has the border color and thickness which your properties when you define your colors still does not get applied to them.
So what you need to do is actually to re-define the control template for your tab item.
I have made basic changes by overriding the Template property of TabItem and added some stuff and bind the BorderThickness, BorderBrush and Background.
<Style x:Key="SidebarTab" TargetType="TabItem">
<Setter Property="Foreground" Value="#303030"></Setter>
<Setter Property="BorderBrush" Value="Red"></Setter>
<Setter Property="BorderThickness" Value="1"></Setter>
<Setter Property="Background" Value="White"></Setter>
<!--I have added this START-->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="TabItem">
<Border BorderThickness="{TemplateBinding BorderThickness}" BorderBrush="{TemplateBinding BorderBrush}"
Background="{TemplateBinding Background}">
<ContentPresenter ContentSource="Header" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<!--I have added this END-->
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Blue"></Setter>
<Setter Property="BorderBrush" Value="Transparent"></Setter>
<Setter Property="BorderThickness" Value="0"></Setter>
<Setter Property="Background" Value="Yellow"></Setter>
</Trigger>
</Style.Triggers>
</Style>
Note:- I have change the property values of Foreground, Background, Border thickness in the above code for test purpose and as I could not find the static resources. You have to change back to your keys.
I hope I have made a point for you to proceed further. Give a try and if you find any issues let me know.

WPF - Change button templated text color on DataTrigger

I have a button that has a control template set (including some controltemplate triggers), and I want to change its text color upon a DataTrigger. I've read that I cannot access the TargetName ("theContent") of the template as it has its own scope, so how can I achieve this?
<Button BorderThickness="0" MaxWidth="94" Height="26" Margin="1,0,0,0">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border x:Name="theBorder" CornerRadius="15" BorderThickness="0" Background="{TemplateBinding Background}">
<Label x:Name="theContent" VerticalContentAlignment="Center" Foreground="White" FontWeight="Bold">
<TextBlock Text="..." TextTrimming="CharacterEllipsis"></TextBlock>
</Label>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="False">
<Setter Property="Background" Value="#1A65AF"></Setter>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="#4d87c0"></Setter>
</Trigger>
<Trigger Property="IsPressed" Value="True">
<Setter Property="Background" Value="#004b95"></Setter>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{...}" Value="..."></Condition>
<Condition Binding="{Binding RelativeSource={RelativeSource Self}, Path=IsEnabled}" Value="False"></Condition>
</MultiDataTrigger.Conditions>
<Setter Property="Background" Value="#ad4811"/>
<Setter Property="Foreground" Value="#7F7F7F" /> // does nothing
<Setter TargetName="theContent" Property="Foreground" Value="#7F7F7F" /> // target not found
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<!--<Button.Content>
<Label x:Name="theContent" VerticalContentAlignment="Center" Foreground="White" FontWeight="Bold">
<TextBlock Text="..." TextTrimming="CharacterEllipsis"></TextBlock>
</Label>
</Button.Content>-->
</Button>
The 2 setters that I tried and don't work are these:
<Setter Property="Foreground" Value="#7F7F7F" /> // does nothing
<Setter TargetName="theContent" Property="Foreground" Value="#7F7F7F" /> // target not found
In your control template, you just need to use TemplateBinding rather than hardcoding the value to White.
<Border x:Name="theBorder" CornerRadius="15" BorderThickness="0" Background="{TemplateBinding Background}">
<Label x:Name="theContent" VerticalContentAlignment="Center" Foreground="{TemplateBinding Foreground}" FontWeight="Bold">
<TextBlock Text="..." TextTrimming="CharacterEllipsis"></TextBlock>
</Label>
</Border>
Doing that will defer to the button Foreground property. Generally, if any properties need to change in your ControlTemplate dynamically, you will want to use TemplateBinding (for example the FontWeight property). Now your StyleTrigger setter will work as expected.
Btw, Foreground="{TemplateBinding Foreground}" is just shorthand for
Foreground="{Binding Foreground, RelativeSource={RelativeSource TemplatedParent}}"

Button background based on the content Textblock text

I am trying to set Button background color based on the TextBlock Text. TextBlock is part of the Button's Content and has been binded to viewmodel property.
<Button Style="{StaticResource ButtonStyle}">
<Button.Content>
<StackPanel>
<TextBlock Text="Title" />
<TextBlock Text="{Binding SomeValue, Mode=OneWay}" />
</StackPanel>
</Button.Content>
</Button>
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Name="bd">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
//HOW TO HERE...
<Trigger Property="Text" Value="SomeText 1">
<Setter TargetName="bd" Property="Background" Value="#b5e61d"/>
</Trigger>
<Trigger Property="Text" Value="SomeText 2">
<Setter TargetName="bd" Property="Background" Value="#99d9ea"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I propose to include title TextBlock in Button's template and then create triggers based on Content value:
<Style x:Key="ButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Name="bd">
<StackPanel>
<TextBlock Text="Title" HorizontalAlignment="Center"/>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</StackPanel>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="Content" Value="SomeText 1">
<Setter TargetName="bd" Property="Background" Value="#b5e61d"/>
</Trigger>
<Trigger Property="Content" Value="SomeText 2">
<Setter TargetName="bd" Property="Background" Value="#99d9ea"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Button Style="{StaticResource ButtonStyle}" Content="{Binding SomeValue}" />

WPF: Setting Foreground of a Label inside a TabItem Header using styles

I have a TabControl which looks like this:
<TabControl>
<TabItem>
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<Canvas ... />
<Label>Tab Number 1</Label>
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem>
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<Canvas ... />
<Label>Tab Number 2</Label>
</StackPanel>
</TabItem.Header>
</TabItem>
</TabControl>
Ok, i like to have a different Text Color when the item is selected. I created a Style for that purpose:
<Style TargetType="{x:Type TabItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Grid Height="60">
<Border x:Name="Border" BorderBrush="#FFC6C7C8"
BorderThickness="1,0,1,0" Margin="-1,0,0,0">
</Border>
<Border x:Name="BorderOverlay" BorderBrush="Transparent"
BorderThickness="1,0,1,0" Margin="-1,0,0,0">
<ContentPresenter x:Name="ContentSite"
VerticalAlignment="Center"
HorizontalAlignment="Center"
ContentSource="Header"
Margin="15,6,15,6">
</ContentPresenter>
</Border>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<!-- What goes here? -->
</Trigger>
<ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I tried by just setting Label.Foreground, but it doesn't seem to work. I also tried it with a TextBlock, which did not worked as well.
I think this question is similar to mine, but the problem wasn't solved in the end:
Setting TabItem foreground color also sets the TabControl foreground color
Thanks for any help.
Try using Style Triggers instead of Control Template Triggers.
Add this to your current style:
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Green" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
Here's a generic style for everyone else.
<Style TargetType="{x:Type TabItem}">
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Green" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter Property="Foreground" Value="Red" />
</Trigger>
</Style.Triggers>
</Style>

How Do I Change The Text Foreground of a WPF TabItem With Nested Text?

I'm looking to have the foreground of the text of a TabItem change whenever the tab becomes active. I was using the following, which was working fine until I changed the type of content being displayed in the tab:
<TabControl Style="{DynamicResource SidebarTabControl}">
<TabItem Header="TabItem" Style="{DynamicResource SidebarTab}" />
</TabControl>
<Style x:Key="SidebarTabForegroundStyleSelected">
<Setter Property="TextBlock.Foreground" Value="White" />
</Style>
<Style x:Key="SidebarTabForegroundStyle">
<Setter Property="TextBlock.Foreground" Value="Black" />
</Style>
<Style x:Key="SidebarTab" TargetType="TabItem">
<Setter Property="Padding" Value="10,12,2,12" />
<Setter Property="BorderThickness" Value="0,1,0,1" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Border Padding="{TemplateBinding Padding}"
Name="tab"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{StaticResource SidebarTabBorderBrush}"
SnapsToDevicePixels="True">
<ContentPresenter Style="{StaticResource SidebarTabForegroundStyle}" Name="content" ContentSource="Header" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="tab" Property="Background" Value="{StaticResource SidebarTabBackgroundBrushSelected}" />
<Setter TargetName="tab" Property="BorderBrush" Value="{StaticResource SidebarTabBorderBrushSelected}" />
<Setter TargetName="content" Property="Style" Value="{StaticResource SidebarTabForegroundStyleSelected}" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="tab" Property="Background" Value="{StaticResource SidebarTabBackgroundBrush}" />
<Setter TargetName="tab" Property="BorderBrush" Value="{StaticResource SidebarTabBorderBrush}" />
<Setter TargetName="content" Property="Style" Value="{StaticResource SidebarTabForegroundStyle}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
When I changed the TabItem to:
<TabControl Style="{DynamicResource SidebarTabControl}">
<TabItem Style="{DynamicResource SidebarTab}">
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<Image Height="16" Source="..\..\Icons\cog.png" />
<TextBlock Text="TabItem" Margin="5,0,0,0" VerticalAlignment="Center" />
</StackPanel>
</TabItem.Header>
</TabItem>
</TabControl>
The foreground of the text no longer turns to white when the tab is selected and back to black when the tab is no longer selected. Everything else still works correctly.
Does anyone know if there is a way to accomplish changing the color of the foreground in the XAML above?
Move the trigger from the control template to the style:
<Grid>
<Grid.Resources>
<SolidColorBrush x:Key="SidebarTabBackgroundBrushSelected" Color="Gray"></SolidColorBrush>
<SolidColorBrush x:Key="SidebarTabBorderBrushSelected" Color="Blue"></SolidColorBrush>
<SolidColorBrush x:Key="SidebarTabBackgroundBrush" Color="LightGray"></SolidColorBrush>
<SolidColorBrush x:Key="SidebarTabBorderBrush" Color="Green"></SolidColorBrush>
<Style x:Key="SidebarTab" TargetType="TabItem">
<Setter Property="Padding" Value="10,12,2,12" />
<Setter Property="BorderThickness" Value="0,1,0,1" />
<Setter Property="Foreground" Value="Blue"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Border Padding="{TemplateBinding Padding}"
Name="tab"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{StaticResource SidebarTabBorderBrush}"
SnapsToDevicePixels="True">
<ContentPresenter Name="content"
ContentSource="Header" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter TargetName="tab" Property="Background" Value="{StaticResource SidebarTabBackgroundBrushSelected}" />
<Setter TargetName="tab" Property="BorderBrush" Value="{StaticResource SidebarTabBorderBrushSelected}" />
</Trigger>
<Trigger Property="IsSelected" Value="False">
<Setter TargetName="tab" Property="Background" Value="{StaticResource SidebarTabBackgroundBrush}" />
<Setter TargetName="tab" Property="BorderBrush" Value="{StaticResource SidebarTabBorderBrush}" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Foreground" Value="Red"></Setter>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<TabControl Style="{DynamicResource SidebarTabControl}">
<TabItem Header="TabItem 1" Style="{DynamicResource SidebarTab}" />
<TabItem Style="{DynamicResource SidebarTab}" >
<TabItem.Header>
<StackPanel>
<TextBlock Text="a"></TextBlock>
<TextBlock Text="b"></TextBlock>
</StackPanel>
</TabItem.Header>
</TabItem>
<TabItem Header="TabItem 3" Style="{DynamicResource SidebarTab}" />
</TabControl>
</Grid>
It looks like the issue is coming up because you are setting the wrong property:
<Style x:Key="SidebarTabForegroundStyleSelected">
<Setter Property="TextBox.Foreground" Value="White" />
</Style>
<Style x:Key="SidebarTabForegroundStyle">
<Setter Property="TextBox.Foreground" Value="Black" />
</Style>
You need to be setting TextElement.Foreground or TextBlock.Foreground
Also, since it is an inherited property, you can just set the AttachedProperty directly on the TabItems, you don't need to assign it specifically to the content.
<TabControl Style="{DynamicResource SidebarTabControl}">
<TabControl.ItemContainerStyle>
<Style TargetType="{x:Type TabItem}">
<Style.Triggers>
<Trigger Property="IsSelected"
Value="True">
<Setter Property="TextElement.Foreground"
Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</TabControl.ItemContainerStyle>
<TabItem>
<TabItem.Header>
<StackPanel Orientation="Horizontal">
<Image Height="16"
Source="..\..\Icons\cog.png" />
<TextBlock Text="TabItem"
Margin="5,0,0,0"
VerticalAlignment="Center" />
</StackPanel>
</TabItem.Header>
Item 1
</TabItem>
<TabItem>
<TabItem.Header>
<TextBlock Text="Tab 2" />
</TabItem.Header>
Item 2
</TabItem>
<TabItem Header="Item 3">
Item 3
</TabItem>
</TabControl>

Resources