Apply style to multiple controls when a style trigger fires in xaml - wpf

When the user enters info I want all the controls to look and act the same way, as a result I have done the following.
The label and textbox controls are in a stackpanel as:
<StackPanel Style="{StaticResource ResourceKey=myInput}" HorizontalAlignment="Left">
<Label Content="Label" Name="label1" />
<TextBox Name="textBox1" ></TextBox>
</StackPanel>
the style "myInput" is:
<Style x:Key="myInput" TargetType="{x:Type StackPanel}">
<Style.Resources>
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource {x:Type Label}}">
<Setter Property="FontSize" Value="12" />
</Style>
<Style TargetType="{x:Type TextBox}">
<Setter Property="Margin" Value="5,-5,2,2"></Setter>
<Setter Property="Height" Value="23"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Style.Triggers>
<Trigger Property="IsFocused" Value="true">
<Setter Property="Background" Value="Blue" >
</Setter>
</Trigger>
</Style.Triggers>
</Style>
</Style.Resources>
</Style>
Now every time that I apply that style to a stackpanel that has a label and a textbox the background of the textbox changes to blue when it receives focus.
How could I set the label's fontweight to bold also when that event fires? I will like to do this with xaml.

Use a DataTrigger on your Label which looks to see if the keyboard focus is inside of the parent StackPanel that contains both objects
<Style TargetType="{x:Type Label}" BasedOn="{StaticResource {x:Type Label}}">
<Setter Property="FontSize" Value="12" />
<Style.Triggers>
<DataTrigger Value="True" Binding="{Binding IsKeyboardFocusWithin,
RelativeSource={RelativeSource AncestorType={x:Type StackPanel}}}">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>

Related

WPF Style Foreground of RadioButton not applied

I have a style for my textblocks, and a style for my radio button.
When I add my radio buttons, they ignore the style for my foreground. The textblock style seems to have precedence and I can't get it the way I want it.
<Style TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
<Setter Property="FontFamily" Value="Daytona Light"/>
<Setter Property="FontSize" Value="22"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Top"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="Foreground" Value="White"/>
</Style>
<Style x:Key="Radio" TargetType="RadioButton" BasedOn="{StaticResource {x:Type ToggleButton}}">
<Setter Property="Foreground" Value="#1a3281"/>
<Setter Property="Background" Value="White"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="RadioButton">
<Border
Background="{TemplateBinding Background}">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsChecked" Value="True">
<Setter Property="Foreground" Value="White"/>
<Setter Property="Background" Value="#1a3281" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I create my radio buttons in a stack panel
<StackPanel Grid.Column="1" Orientation="Horizontal">
<StackPanel.Resources>
<Style TargetType="RadioButton" BasedOn="{StaticResource Radio}">
<Setter Property="Margin" Value="50, 0, 0, 20"/>
<Setter Property="Width" Value="250"/>
<Setter Property="Height" Value="60"/>
<Setter Property="HorizontalAlignment" Value="Center"/>
<Setter Property="VerticalAlignment" Value="Center"/>
</Style>
</StackPanel.Resources>
<RadioButton GroupName="MainSelection" Command="{Binding ShowVideoCommand}" Content="Video">
</RadioButton>
<RadioButton GroupName="MainSelection" Command="{Binding ShowPresentationCommand}" Content="Presentation">
</RadioButton>
<RadioButton GroupName="MainSelection" Command="{Binding ShowSimulatorCommand}" Content="Simulator">
</RadioButton>
</StackPanel>
When I run my app, I see the radio buttons as full white rectangles. When the RadioButton is checked, the style for the background works fine (becomes blue, with text still white).
What am I doing wrong for my foreground style? Why is the textblock style always wins over my radio button style?
Even when I set Foreground="Red" in my RadioButton as follows
<RadioButton Foreground="Red" GroupName="MainSelection" Command="{Binding ShowVideoCommand}" Content="Video">
it won't show up. Text is always white.

Default style for TextBlock not being picked up after applying a style key

I have a <ResourceDictionary> containing this:
<Style TargetType="TextBlock">
<Setter Property="FontFamily" Value="..\..\Fonts\#Roboto"/>
<Setter Property="FontSize" Value="14"/>
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
This works fine.
Now I've added another style:
<Style x:Key="MyText" TargetType="{x:Type TextBlock}">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="FontWeight" Value="SemiBold"/>
</Style>
However, after changing my <TextBlock> to <TextBlock Style="{StaticResource MyText}"/> - only the styles within the 2nd style block are picked up. E.g. the FontFamily, FontSize and TextWrapping are now ignored.
How can I have a default for a TextBlock, and then add to it? I don't want to add an x:Key to the 'default' style as this is in use throughout the system already.
I think you just need to base your keyed style on the type. See example below.
Note the BasedOn="{StaticResource {x:Type TextBlock}}"
<Window.Resources>
<Style TargetType="TextBlock">
<Setter Property="FontSize" Value="14"/>
<Setter Property="Foreground" Value="Green" />
<Setter Property="TextWrapping" Value="Wrap"/>
</Style>
<Style x:Key="MyText" TargetType="TextBlock">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="FontWeight" Value="SemiBold"/>
</Style>
<Style x:Key="MyAppendedStyles" TargetType="TextBlock" BasedOn="{StaticResource {x:Type TextBlock}}">
<Setter Property="Foreground" Value="Red"/>
<Setter Property="FontWeight" Value="SemiBold"/>
</Style>
</Window.Resources>
<StackPanel>
<TextBlock Text="Hello" />
<TextBlock Style="{StaticResource MyText}" Text="Style Key" />
<TextBlock Style="{StaticResource MyAppendedStyles}" Text="Style Key" />
</StackPanel>

Background color is not changing in DataTrigger

I have some problem while changing background color of Button using datatrigger but it is not happen.
My code is this
<Window x:Class="DataBinding.DataTrigger2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="DataTrigger2" Height="300" Width="300">
<Button Height="50" Name="btn">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Control.Background" Value="YellowGreen"></Setter>
<Setter Property="Control.Foreground" Value="Brown"></Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=btn, Path=IsPressed}" Value="True">
<Setter Property="Control.Background" Value="Purple"></Setter>
<Setter Property="Control.Foreground" Value="Red"></Setter>
<Setter Property="Control.FontSize" Value="20"></Setter>
<Setter Property="Control.FontWeight" Value="Light"></Setter>
<Setter Property="Control.Width" Value="150"></Setter>
<Setter Property="Control.Height" Value="50"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<Button.Content>
The Gaming World Inc.
</Button.Content>
</Button>
The reason why you don't see the Button.Background colour change when you click the mouse is because of the default ControlTemplate that defines what the it should look like in different states, eg. pressed, disabled. etc. These are defined in the VisualStateManager.VisualStateGroups section of the ControlTemplate and they potentially override your Background changes.
As simple proof of this, we can provide a basic ControlTemplate for the Button without the VisualStateManager.VisualStateGroups section and then you will see your Background colour change. Try this:
<Button Height="50" Name="btn">
<Button.Style>
<Style TargetType="Button">
<Setter Property="Control.Background" Value="YellowGreen"></Setter>
<Setter Property="Control.Foreground" Value="Brown"></Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border Background="{TemplateBinding Background}">
<ContentPresenter />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=btn, Path=IsPressed}" Value="True">
<Setter Property="Control.Background" Value="Purple"></Setter>
<Setter Property="Control.Foreground" Value="Red"></Setter>
<Setter Property="Control.FontSize" Value="20"></Setter>
<Setter Property="Control.FontWeight" Value="Light"></Setter>
<Setter Property="Control.Width" Value="150"></Setter>
<Setter Property="Control.Height" Value="50"></Setter>
</DataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
<Button.Content>
The Gaming World Inc.
</Button.Content>
</Button>
You can find the original/default ControlTemplate for the Button control in the Button Styles and Templates page on MSDN... you may want to copy more of that ControlTemplate into your one to make your Button look more like the original one.

Why is WPF ComboBox styling not as expected?

I have a WPF app with a ComboBox where I want to style the items but get an unexpected behaviour depending upon which item is selected.
The following XAML snippet demonstrates the problem:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Page.Resources>
<Style x:Key="ItemStyle" TargetType="{x:Type ComboBoxItem}">
<Style.Triggers>
<Trigger Property="Content" Value="ABC">
<Setter Property="FontStyle" Value="Oblique"/>
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="BoxStyle" TargetType="{x:Type ComboBox}">
<Style.Triggers>
<Trigger Property="Text" Value="ABC">
<Setter Property="FontStyle" Value="Italic"/>
<Setter Property="Foreground" Value="Red"/>
</Trigger>
</Style.Triggers>
</Style>
</Page.Resources>
<Border Width="200">
<ComboBox Style="{StaticResource BoxStyle}"
ItemContainerStyle="{StaticResource ItemStyle}"
Height="20">
<ComboBoxItem>ABC</ComboBoxItem>
<ComboBoxItem>DEF</ComboBoxItem>
<ComboBoxItem>GHI</ComboBoxItem>
</ComboBox>
</Border>
</Page>
This displays a simple ComboBox with three items; ABC, DEF and GHI. Note that ABC is shown in the dropdown with oblique, red text and also in the selection box when selected.
However, if I then open the dropdown again all 3 items are shown oblique and red.
If the DEF or GHI items are selected then these show in normal font, black and on opening the dropdown again show correctly - with ABC still showing oblique, red.
What am I doing wrong?
This is because of Dependency Property Value Precedence. When ABC is selected the ComboBoxItems in the DropDown inherit the FontStyle and Foreground from the ComboBox.
This will fix the code as the ComboBoxItems won't inherit FontStyle and Foreground from the ComboBox:
<Page.Resources>
<Style x:Key="ItemStyle"
TargetType="{x:Type ComboBoxItem}">
<Setter Property="FontStyle"
Value="Normal" />
<Setter Property="Foreground"
Value="Black" />
<Style.Triggers>
<Trigger Property="Content"
Value="ABC">
<Setter Property="FontStyle"
Value="Oblique" />
<Setter Property="Foreground"
Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="BoxStyle"
TargetType="{x:Type ComboBox}">
<Style.Triggers>
<Trigger Property="Text"
Value="ABC">
<Setter Property="FontStyle"
Value="Italic" />
<Setter Property="Foreground"
Value="Red" />
</Trigger>
</Style.Triggers>
</Style>
</Page.Resources>
<Border Width="200">
<ComboBox Style="{StaticResource BoxStyle}"
ItemContainerStyle="{StaticResource ItemStyle}"
Height="20">
<ComboBoxItem>ABC</ComboBoxItem>
<ComboBoxItem>DEF</ComboBoxItem>
<ComboBoxItem>GHI</ComboBoxItem>
</ComboBox>
</Border>

WPF Grid - How to apply a style for just one column?

I have a WPF Grid with many rows and columns, all containing things like TextBlocks and TextBoxes.
For this specific situation I want all the stuff in column 1 to have padding, and all the stuff in column 2 to be aligned right. It seems to be very non-WPF to have to set those properties on each item in the grid.
I know I can create a style for all TextBlocks within a grid by doing something like this:
<Grid>
<Grid.Resources>
<Style TargetType="{x:Type TextBox}">
<Setter Property="HorizontalAlignment" Value="Right"/>
</Style>
</Grid.Resources>
</Grid>
But is there a way to apply that style to only the controls in say, column 2?
Should I be using a different control?
Here's what I usually do:
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type TextBlock}}">
<Style.Triggers>
<Trigger Property="Grid.Column" Value="0">
<Setter Property="Margin" Value="0,0,2,0" />
</Trigger>
<Trigger Property="Grid.Column" Value="2">
<Setter Property="Margin" Value="20,0,2,0" />
</Trigger>
</Style.Triggers>
</Style>
You can define some styles like below and assign them to your Column.ElementStyle property:
<Window.Resources>
<Style x:Key="elementStyle" TargetType="TextBlock">
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="Margin" Value="2,0,2,0" />
</Style>
<Style x:Key="rightElementStyle" BasedOn="{StaticResource elementStyle}" TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Right" />
</Style>
<Style x:Key="centerElementStyle" BasedOn="{StaticResource elementStyle}" TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>
</Window.Resources>
<dg:DataGrid AutoGenerateColumns="False">
<dg:DataGrid.Columns>
<dg:DataGridTextColumn Binding={Binding Path=Name}
Header="Name"
ElementStyle="{StaticResource centerElementStyle}"/>
<dg:DataGridTextColumn Binding={Binding Path=Amount}
Header="Amount"
ElementStyle="{StaticResource rightElementStyle}"/>
</dg:DataGrid.Columns>
</dg:DataGrid>

Resources