In my C# / WPF / .NET 4.5 app I would like to implement a Trigger
that toggles the background opacity of a control without changing its color.
Normally to set the background brush of a control, I would use the following Setter
:
<Setter TargetName="TargetControl" Property="Background">
<Setter.Value>
<SolidColorBrush Color="Red" Opacity="0.2"/>
</Setter.Value>
Now I am in a situation where I have to change the opacity only and not the color. What would my setter look like in this case, where I don't care what color the background is but I want to preserve the color while changing the opacity?
The reason for this is that I am working on an ItemsControl
where the background color changes depending on the item's AlternationIndex
:
<ItemsControl ItemsSource="{Binding SomeCollection}" AlternationCount="6">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid x:Name="GridWithin">
<!-- ... -->
</Grid>
<DataTemplate.Triggers>
<!-- Aternating colors for each row -->
<Trigger Property="ItemsControl.AlternationIndex" Value="0">
<Setter TargetName="GridWithin" Property="Background">
<Setter.Value>
<SolidColorBrush Color="Red" Opacity="0.2"/>
</Setter.Value>
</Setter>
</Trigger>
<Trigger Property="ItemsControl.AlternationIndex" Value="1">
<Setter TargetName="AllGesturesDataTemplateGrid" Property="Background">
<Setter.Value>
<SolidColorBrush Color="Green" Opacity="0.2"/>
</Setter.Value>
</Setter>
</Trigger>
<!-- ... -->
<!-- Highlight when a hit is registered -->
<DataTrigger>
<DataTrigger.Conditions>
<Condition Binding="{Binding IsHit}" Value="True" />
</MultiDataTrigger.Conditions>
<!-- The culprit -->
<Setter TargetName="GridWithin" Property="Background">
<Setter.Value>
<SolidColorBrush Opacity="0.7"/>
</Setter.Value>
</Setter>
<!-- /culprit -->
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
It took me a little while to think of the best way to do this... it turns out that it was trickier than I had first thought. All the same, it is possible, but it does involve quite a lot of code. In order to be able to target the actual Opacity
property of the Background Brush
object, you'll need to use a StoryBoard
... that's why this code example is so verbose.
Because we need to use a Storyboard
object in the DataTrigger
, that means that we must use the DataTrigger.EnterActions
as a Storyboard
cannot be used in the normal DataTrigger.Setters
collection. This follows that we must also use the DataTrigger.ExitActions
to provide another Storyboard
that sets the Opacity
property back to its original value. Try this:
<Grid Name="YourGrid">
<Grid.Background>
<SolidColorBrush Color="Green" Opacity="0.2" />
</Grid.Background>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=YourGrid}"
Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="Background.(SolidColorBrush.Opacity)">
<LinearDoubleKeyFrame Value="0.7" KeyTime="0:0:0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimationUsingKeyFrames
Storyboard.TargetProperty="Background.(SolidColorBrush.Opacity)">
<LinearDoubleKeyFrame Value="0.2" KeyTime="0:0:0"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
Despite the amount of code required to implement this method, it does do exactly what you were after. However, there is a simpler way to get the same overall effect, but with slightly less code. You could simply add a Rectangle
into the back of each Grid
cell, or division and set the colours and opacity on that instead. Using this method, you could simply set the Rectangle.Opacity
value directly, although you would be using extra controls... the choice is yours.
This answer is almost identical to @Sheridans, but it saves a few lines of XAML (and there are always too many as it is...)
Grid Name="YourGrid">
<Grid.Background>
<SolidColorBrush Color="Green" Opacity="0.2" />
</Grid.Background>
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=YourGrid}"
Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard Storyboard.TargetProperty="Background.(SolidColorBrush.Opacity)">
<DoubleAnimation To="0.7" Duration="0" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard Storyboard.TargetProperty="Background.(SolidColorBrush.Opacity)">
<DoubleAnimation To="0.2" Duration="0" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
</Grid>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With