Foreground Color of Custom Button (ControlPresenter) - wpf

I am attempting to define a global button style in App.xaml, and it's mostly working as I expect. However, I just cannot figure out how to get the Foreground to work correctly. No matter what I do, I am getting the style of the default TextBlock (which sets the color to White).
<Style TargetType="{x:Type Button}">
<Setter Property="Margin" Value="3, 5" />
<Setter Property="OverridesDefaultStyle" Value="True" />
<Setter Property="FocusVisualStyle"
Value="{StaticResource ButtonFocusVisual}" />
<Setter Property="Foreground" Value="Red" />
<Setter Property="Padding" Value="5" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Grid x:Name="gridMainButton"
RenderTransformOrigin="0.5, 0.5">
<Grid.RenderTransform>
<ScaleTransform x:Name="scaleTransform"
CenterX="0.5"
CenterY="0.5" />
</Grid.RenderTransform>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates" >
<VisualState x:Name="Normal" />
<VisualState x:Name="MouseOver" />
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="scaleTransform"
Storyboard.TargetProperty="ScaleX"
Duration="0"
To="0.85" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Ellipse x:Name="ellipse"
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
StrokeThickness="2"
Stroke="{StaticResource standardBackground}"
Fill="{StaticResource standardBackground}" />
<ContentPresenter HorizontalAlignment="Center"
VerticalAlignment="Center"
Margin="4, 8"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I guess I could change the ContentPresenter to a TextBlock, which would be ok for this particular application, but I'm looking for a more generic solution.
Thanks,
wTs

Like Markus Hütter said, the problem is probably that you have an implicit Style for a TextBlock defined and when the Button Content is set to a string, a TextBlock will be created where you have the ContentPresenter in the Template. This TextBlock will pick up the implicit Style and that's why you're getting this problem.
You can disable the implicit Style for a TextBlocks that is created in place for a string by specifying a DataTemplate for string. Add the following to App.xaml
<Application ...>
<Application.Resources>
<DataTemplate xmlns:sys="clr-namespace:System;assembly=mscorlib"
DataType="{x:Type sys:String}">
<TextBlock Text="{Binding}">
<TextBlock.Resources>
<Style TargetType="{x:Type TextBlock}"/>
</TextBlock.Resources>
</TextBlock>
</DataTemplate>
<!--...-->
</Application.Resources>
</Application>

you seem to be using a custom style for textblock (if you say Foreground color is white) lets call this StandardTextBlockStyle.
Within your button style inside the outer grid. include this:
<Grid x:Name="gridMainButton">
<Grid.Resources>
<Style TargetType="TextBlock" BasedOn="{StaticResource StandardTextBlockStyle}">
<Setter Property="Foreground" Value="Black"/>
</Style>
</Grid.Resources>
<!-- ...-->
</Grid>
this should override the default TextBlock style.

I had similar issue, there was a global TextBlock style and I was not able to override it in other controls where custom color/font was needed.
Based on Fredrik Hedblad & Pavlo Glazkov (from here) responses, the following solution worked for me:
<DataTemplate DataType="{x:Type System:String}">
<TextBlock Text="{Binding}">
<TextBlock.Resources>
<Style TargetType="{x:Type TextBlock}" BasedOn="{StaticResource {x:Type TextBlock}}">
<Setter Property="Foreground" Value="{Binding RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}, Path=(TextElement.Foreground),
FallbackValue={StaticResource Colors_ThemeForeground_SCBrush}, TargetNullValue={StaticResource Colors_ThemeForeground_SCBrush}}"/>
</Style>
</TextBlock.Resources>
</TextBlock>
</DataTemplate>
Thanks,
RDV

Related

How to avoid that a Coloranimation in a ControlTemplate gets applied to every object using the template

I declared ColorAnimations inside a ControlTemplate of a Style.
What it should do:
Whenever the mouse hovers over the object the color of this specific object should be animated.
What it does instead:
Animating the color of EVERY object the style is applied to whenever I hover over one of them, even though the property activating the animation is not changing on all objects.
What I tried before:
I tried using an Eventrigger instead of a normal trigger but the problem persists.
I also tried using the "Name" property not "x:Name" but this didn't help either.
Also not using Storyboard.TargetName but Storyboard.Target and using a binding with RelativeSource to let it find the object.. and still every object using this style gets animated whenever I hover over any of them
It works as intended if I use Setters to change the background instead of Storyboards and ColorAnimations.
The Style
<Style x:Key="Fraction_ScrollViewer_ScrollBar_Thumb" TargetType="{x:Type Thumb}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Thumb}">
<Border
x:Name="Border"
CornerRadius="5"
Background="{TemplateBinding Background}"
BorderThickness="0" />
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard
Name="IsMouseOver_True"
HandoffBehavior="Compose">
<Storyboard>
<ColorAnimation
Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"
To="{StaticResource 'Color_CoolGrey'}"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard
Name="IsMouseOver_False">
<Storyboard>
<ColorAnimation
Storyboard.TargetName="Border"
Storyboard.TargetProperty="Background.(SolidColorBrush.Color)"
To="{StaticResource 'Color_MidGrey'}"
Duration="0:0:0.2" />
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
The Thumb style is used in a Scrollbar style which is used in a ScrollViewer.
The Scrollviewer Style is then used in 2 locations:
1:
<Style x:Key="LabelTreeView" TargetType="{x:Type TreeView}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TreeView}">
<ScrollViewer
Style="{StaticResource ScrollViewer}"
Focusable="False"
CanContentScroll="False"
Padding="4">
<ItemsPresenter />
</ScrollViewer>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
2:
<ScrollViewer
Style="{StaticResource ScrollViewer}"
HorizontalScrollBarVisibility="Disabled"
VerticalScrollBarVisibility="Auto">
<ItemsControl
BorderThickness="0"
Background="{StaticResource Brush_Transparent}"
ItemTemplate="{StaticResource CharacterSequenceChar}"
ItemsSource="{Binding DisplayedCharacterSequenceCharacters}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
</ItemsControl>
</ScrollViewer>
What is causing this behaviour and how to avoid it with still using animations?
Apparently all Buttons share the same Brush instance in their Background property.
You could explicitly assign a separate Brush for each Border in the Template:
<Border x:Name="Border" ...>
<Border.Background>
<SolidColorBrush Color="{Binding Background.Color,
RelativeSource={RelativeSource TemplatedParent}}"/>
</Border.Background>
</Border>

How get the click event of a ListBoxItem whilst using ItemTemplate

<Window.Resources>
<Style TargetType="ListBoxItem">
<Style.Triggers>
<EventTrigger RoutedEvent="PreviewGotKeyboardFocus">
<BeginStoryboard>
<Storyboard>
<BooleanAnimationUsingKeyFrames
Storyboard.TargetProperty="(ListBoxItem.IsSelected)">
<DiscreteBooleanKeyFrame KeyTime="0" Value="True"/>
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<Trigger Property="IsSelected" Value="True">
<Setter Property="Opacity" Value="1.0" />
</Trigger>
</Style.Triggers>
<Style.Resources>
<SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey}"
Color="Blue"/>
</Style.Resources>
<Setter Property="Background" Value="Red" />
<Setter Property="MaxHeight" Value="75" />
</Style>
<DataTemplate x:Key="dtTeamInGame">
<WrapPanel >
<TextBox x:Name="txtPath" Text="{Binding Path = Number, Mode=TwoWay}" MinWidth="35" ></TextBox>
<TextBox x:Name="txtPath2" Text="{Binding Path = KnownName, Mode=TwoWay}" MinWidth="125" ></TextBox>
</WrapPanel>
</DataTemplate>
</Window.Resources>
<Grid>
<ListBox x:Name="listBox" ItemTemplate="{DynamicResource dtTeamInGame}" HorizontalAlignment="Left" Height="100" Margin="29,184,0,0" VerticalAlignment="Top" Width="381">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListViewItem_PreviewMouseLeftButtonDownHome" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
<Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="335,108,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
</Grid>
I have a Listbox which contains Textboxes in the item and I would like for when I click the textbox the item the textbox is in should be selected. Before adding:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<EventSetter Event="PreviewMouseLeftButtonDown" Handler="ListViewItem_PreviewMouseLeftButtonDownHome" />
</Style>
</ListBox.ItemContainerStyle>
the list box item would be selected if I clicked the textbox within an item. If I remove the container style above it works as intended but I need the container style because I would like to carry out some tasks if the user clicks an item that is already selected.
It sounds like you want to keep behavior from the default ListBoxItem style, but you also want to add your own stuff to it. That's easy: Use the BasedOn property of the style to inherit from the existing default style.
<ListBox.ItemContainerStyle>
<Style
TargetType="ListBoxItem"
BasedOn="{StaticResource {x:Type ListBoxItem}}"
>
<!-- Your stuff -->

Handling Button states in WPF

I have a WPF application with a menu bar with some buttons to navigate to the different sections.
All the buttons have an style with a VisualState property, so all of them have a Normal, OnMouseOver and Pressed state different styles. And all the buttons, once pressed, execute a Command on the ModelView.
What i want is that each time a button is pressed, first it keeps the Pressed state until another button is pressed and second, it is possible to change the button state from the Command event executed at the ModelView side.
The Code:
<Style x:Key="MainButtonStyle" TargetType="Button">
<Setter Property="Width" Value="120"/>
<Setter Property="Height" Value="60"/>
<Setter Property="Margin" Value="5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Grid Background="White" x:Name="ButtonGrid">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="MouseOver">
<Storyboard>
<ColorAnimation Duration="0:0:0.3" Storyboard.TargetName="ButtonGrid" Storyboard.TargetProperty="Background.Color" To="Cyan"/>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ColorAnimation Duration="0:0:0.2" Storyboard.TargetName="ButtonGrid" Storyboard.TargetProperty="Background.Color" To="DarkSalmon"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
The buttons using the style:
<ItemsControl Margin="10" Grid.Column="1" Grid.RowSpan="2" ItemsSource="{Binding HeaderButtons}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Style="{StaticResource MainButtonStyle}" Content="{Binding content}"
Command="{Binding DataContext.ChangePageContainerCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"
CommandParameter="{Binding containerType}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
And i think that the ModelView is not relevant since it does nothing on the Button VisualState since i don't know how to pass it a reference to the Button caller (as parameter or something?).
I have seen in other posts that people recommend to use a ToggleButton in place of a Button and set the IsChecked to true, but i don´t know where should i set that property, i mean, should i set it at the XAML or at code? and how?
What i want is that each time a button is pressed, first it keeps the Pressed state until another button is pressed
What you want is a group of RadioButtons, but probably ones that are styled to look like normal Buttons. Here is a small example of some RadioButtons that look somewhat like Buttons:
<StackPanel Orientation="Horizontal">
<StackPanel.Resources>
<Style TargetType="{x:Type RadioButton}">
<Setter Property="BorderBrush" Value="Blue" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type RadioButton}">
<Border Name="Border" CornerRadius="4" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="2" Padding="10, 5" VerticalAlignment="Top" Margin="0,0,5,0">
<ContentPresenter />
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="Border" Property="Border.Background" Value="LightBlue" />
</Trigger>
<Trigger Property="IsChecked" Value="True">
<Setter TargetName="Border" Property="Border.Background" Value="LightGreen" />
<Setter TargetName="Border" Property="Border.BorderBrush" Value="Green" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</StackPanel.Resources>
<RadioButton Content="Button 1" />
<RadioButton Content="Button 2" />
<RadioButton Content="Button 3" />
</StackPanel>
Note that I have added some basic state functionality using basic Triggers... using the VisualStateManager is simply unnecessary here and seems to be causing extra problems for you. The VisualStateManager really comes into its own when we write complex UserControls or CustomControls that require definite separate states. For your simple purposes, you should just use Triggers instead.
is it possible to change the button state from the Command event executed at the ModelView side?
The answer to your second question has been answered so many times before that UI won't go into it all again here. Suffice it to say that you can find details in the How to bind RadioButtons to an enum? question (or in many other online sources). In short though, you need to define an enum, declare an EnunmToBoolConverter to enable you to data bind your enum to the bool IsChecked property of each RadioButton. You will then be able to set each Button to be selected or not from the view model.

Best practice to pipe WPF animation trigger from one ControlTemplate element to another

After reading several SO posts (here, here, and here) I still can't find any way to solve my problem... Basically, I redefined Button layout, and packed it up in a style. The new Button ControlTemplate contains a Rectangle I want to animate on Button click. Which TargetProperty do I have to use in my animation? Following is what I done :
UserControl x:Class="OfficeTourismeBrantome.Views.MainMenuView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="800" d:DesignWidth="300">
<UserControl.Resources>
<Style x:Key="MenuItemButtonStyle" TargetType="Button">
<Setter Property="FontSize" Value="35" />
<Setter Property="FontFamily" Value="Segoe" />
<Setter Property="Foreground" Value="#FFEBEDEA" />
<!--<Setter Property="Height" Value="{Binding MenuLayout.MenuItemSize.Height}" />-->
<Setter Property="HorizontalContentAlignment" Value="Right" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Canvas HorizontalAlignment="Stretch">
<ContentPresenter Canvas.Left="{Binding MenuLayout.MenuItemLeftMargin}" HorizontalAlignment="Center"
VerticalAlignment="Center"/>
<Rectangle
Name="test"
Width="0"
Height="3"
Fill="Aqua"/>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
<!-- Which targetProperty should I use to animate ControlTemplate Rectangle ?-->
From="0.0"
To="10.0"
Duration="0:0:2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</Style.Triggers>
</Style>
</UserControl.Resources>
<ItemsControl Name="menuButtonContainer" ItemsSource="{Binding Items}" Margin="{Binding MenuLayout.MenuMargin}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Vertical" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button
Style="{StaticResource ResourceKey=MenuItemButtonStyle}"
Margin="{Binding ElementName=menuButtonContainer,
Path=DataContext.MenuLayout.MenuItemMargin}"
Height="{Binding ElementName=menuButtonContainer,
Path=DataContext.MenuLayout.MenuItemSize.Height}"
Content="{Binding Text}"
Command="{Binding ElementName=menuButtonContainer,
Path=DataContext.ChangeThemeCommand}"
CommandParameter="{Binding Id}"
/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
I may be wrong in my implementation, still trying to understand WPF subtilities... What's the best way to achieve my goal?
Many thanks for your answers !
Which target property you want to animate is the question you have to ask yourself ! Do you want to change the rectangle's Width ? Its Opacity ? ...
Best practice... I don't know, but that's one way to do it :
<ControlTemplate TargetType="Button">
[...]
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Button.Click">
<EventTrigger.Actions>
<BeginStoryboard>
<Storyboard TargetName="test" TargetProperty="Width">
<DoubleAnimation From="0.0" To="10.0" Duration="0:0:2" />
</Storyboard>
</BeginStoryboard>
</EventTrigger.Actions>
</EventTrigger>
</ControlTemplate.Triggers>

WPF Style Trigger for DataGridRow Background Color Trumped by AlternatingRowBackground Brush

I have a WPF DataGrid which has an AlternatingRowBackground brush. It's configured to color every other row. I'd like to do something on mouse over that highlights the current row. However, the Style Trigger seems to be losing out to the AlternatingRowBackground brush. I get the desired row coloration on the mouse over... but only on the rows that are not painted with the AlternatingRowBackground brush.
Here is the Style in Windows.Resources:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Skins/MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="Red" />
<Setter Property="FontWeight"
Value="ExtraBold" />
<Setter Property="Height"
Value="20" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</Window.Resources>
And here is the DataGrid:
<DataGrid Margin="25,15,25,0"
VerticalAlignment="Top"
ItemsSource="{Binding DocumentTypeList}"
AutoGenerateColumns="False"
Height="500"
AlternationCount="2"
FrozenColumnCount="2"
AlternatingRowBackground="{DynamicResource AlternatingRow}">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Abbreviation}"
Header="Abbreviation" />
<DataGridTextColumn Binding="{Binding Title}"
Header="Title" />
<DataGridTextColumn Binding="{Binding Fee}"
Header="Fee" />
<DataGridTextColumn Binding="{Binding SpecialInstructions}"
Header="Special Instructions" />
</DataGrid.Columns>
</DataGrid>
Is there a way to declare the absolute winner? Is the issue one of a hierarchy? It seems to me that the AlternatingRowBackground brush wins out because it is directly associated with the most specific part of the declaration.
Update: Here is the correct syntax, based upon #Val's guidance:
<Window.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Skins/MainSkin.xaml" />
</ResourceDictionary.MergedDictionaries>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="Red" />
<Setter Property="FontWeight"
Value="ExtraBold" />
<Setter Property="Height"
Value="20" />
</Trigger>
</Style.Triggers>
</Style>
<Style TargetType="{x:Type DataGrid}">
<Setter Property="AlternatingRowBackground" Value="{DynamicResource AlternatingRow}"/>
</Style>
</ResourceDictionary>
</Window.Resources>
And the DataGrid (minus the AlternatingRowBackground brush):
<DataGrid Margin="25,15,25,0"
VerticalAlignment="Top"
ItemsSource="{Binding DocumentTypeList}"
AutoGenerateColumns="False"
Height="500"
AlternationCount="2"
FrozenColumnCount="2">
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding Abbreviation}"
Header="Abbreviation" />
<DataGridTextColumn Binding="{Binding Title}"
Header="Title" />
<DataGridTextColumn Binding="{Binding Fee}"
Header="Fee" />
<DataGridTextColumn Binding="{Binding SpecialInstructions}"
Header="Special Instructions" />
</DataGrid.Columns>
</DataGrid>
There's two ways to do this, neither is particularly obvious. Since DataGridRow transfers (in code) the background property from the parent DataGrid to a local value in the row, as you noted it will take precedence over the value set by your trigger.
The first (and simplest) way is to not use the AlternatingRowBackground or RowBackground but instead use triggers to alternate the background color as Val suggested. His example is not complete though and will not work as-is. The correct style and usage would be as follows. Note that you need to set the AlternationCount on DataGrid or else the rows will never get alternating indexes.
<DataGrid AlternationCount="2">
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Background" Value="White"/>
<Setter Property="FontWeight" Value="Normal"/>
<Style.Triggers>
<Trigger Property="AlternationIndex" Value="1">
<Setter Property="Background" Value="Wheat"/>
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="Khaki"/>
</Trigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
</DataGrid>
The second option is to use the VisualStateManager. This gives you far more control over the different visual states but it is more verbose. Fortunately it's quite easy to copy the default control template using Blend. Most of the following is unchanged except the Storyboard in the MouseOver state and I've set a background on the selectiveScrollingGrid.
Sorry for the wrap, but like I said, it's a bit more verbose.
<DataGrid AlternationCount="2" AlternatingRowBackground="Wheat">
<DataGrid.RowStyle>
<Style TargetType="DataGridRow">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridRow">
<Border x:Name="DGR_Border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
SnapsToDevicePixels="True">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal"/>
<VisualState x:Name="Normal_AlternatingRow"/>
<VisualState x:Name="Unfocused_Editing"/>
<VisualState x:Name="Normal_Editing"/>
<VisualState x:Name="Unfocused_Selected"/>
<VisualState x:Name="Normal_Selected"/>
<VisualState x:Name="MouseOver_Unfocused_Editing"/>
<VisualState x:Name="MouseOver_Editing"/>
<VisualState x:Name="MouseOver_Unfocused_Selected"/>
<VisualState x:Name="MouseOver_Selected"/>
<VisualState x:Name="MouseOver">
<Storyboard Storyboard.TargetName="Highlight">
<ColorAnimation Duration="0" Storyboard.TargetProperty="Color" To="Khaki"/>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<SelectiveScrollingGrid x:Name="selectiveScrollingGrid">
<SelectiveScrollingGrid.Background>
<SolidColorBrush x:Name="Highlight" Color="Transparent"/>
</SelectiveScrollingGrid.Background>
<SelectiveScrollingGrid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</SelectiveScrollingGrid.ColumnDefinitions>
<SelectiveScrollingGrid.RowDefinitions>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</SelectiveScrollingGrid.RowDefinitions>
<DataGridCellsPresenter Grid.Column="1" ItemsPanel="{TemplateBinding ItemsPanel}" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
<DataGridDetailsPresenter Grid.Column="1" Grid.Row="1" SelectiveScrollingGrid.SelectiveScrollingOrientation="{Binding AreRowDetailsFrozen, ConverterParameter={x:Static SelectiveScrollingOrientation.Vertical}, Converter={x:Static DataGrid.RowDetailsScrollingConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}" Visibility="{TemplateBinding DetailsVisibility}"/>
<DataGridRowHeader Grid.RowSpan="2" SelectiveScrollingGrid.SelectiveScrollingOrientation="Vertical" Visibility="{Binding HeadersVisibility, ConverterParameter={x:Static DataGridHeadersVisibility.Row}, Converter={x:Static DataGrid.HeadersVisibilityConverter}, RelativeSource={RelativeSource AncestorType={x:Type DataGrid}}}"/>
</SelectiveScrollingGrid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.RowStyle>
</DataGrid>
What's worked for me in the past with this kind of thing, is to use a setter outside the triggers eg:
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<Trigger Property="IsMouseOver"
Value="True">
<Setter Property="Background"
Value="Red" />
<Setter Property="FontWeight"
Value="ExtraBold" />
<Setter Property="Height"
Value="20" />
</Trigger>
</Style.Triggers>
<Setter Property="AlternatingRowBackground"
Value="{DynamicResource AlternatingRow}"/>
</Style>
And them remove the property binding on the DataGrid itself. Although I usually do this with data triggers, and not usually with dynamic resource bindings. But still might be worth a shot

Resources