How to animate Opacity of a DropShadowEffect?
Asked Answered
P

2

9

I have a WPF project with a border using the following style. The plan is to get the glow effect to fade in when the mouse moves over the border, and fade out when it leaves.

<Style x:Key="BorderGlow" TargetType="Border">
    <Style.Resources>
        <Storyboard x:Key="GlowOn">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(DropShadowEffect.Opacity)">
                <SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="1"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
        <Storyboard x:Key="GlowOff">
            <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(DropShadowEffect.Opacity)">
                <SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/>
            </DoubleAnimationUsingKeyFrames>
        </Storyboard>
    </Style.Resources>

    <Setter Property="CornerRadius" Value="6,1,6,1" />
    <Setter Property="BorderBrush" Value="{StaticResource SelectedBorder}" />
    <Setter Property="BorderThickness" Value="1" />
    <Setter Property="Background" Value="{StaticResource DeselectedBackground}" />
    <Setter Property="RenderTransformOrigin" Value="0.5,0.5" />
    <Setter Property="TextBlock.Foreground" Value="{StaticResource SelectedForeground}" />

    <Setter Property="RenderTransform">
        <Setter.Value>
            <RotateTransform Angle="90"/>
        </Setter.Value>
    </Setter>

    <Setter Property="Effect">
        <Setter.Value>
            <DropShadowEffect ShadowDepth="0" BlurRadius="8" Color="#FFB0E9EF"/>
        </Setter.Value>
    </Setter>

    <Style.Triggers>
        <Trigger Property="IsMouseOver" Value="True">

            <Trigger.EnterActions>
                <BeginStoryboard Storyboard="{StaticResource GlowOn}"/>
            </Trigger.EnterActions>

            <Trigger.ExitActions>
                <BeginStoryboard Storyboard="{StaticResource GlowOff}"/>
            </Trigger.ExitActions>

        </Trigger>
    </Style.Triggers>
</Style>

The problem is, nothing happens! The animation works if I change the "DropShadowEffect" to "UIElement" in the Storyboard TargetProperty, but this fades the entire control.

How do I fade just the DropShadowEffect?

Pernickety answered 15/9, 2009 at 5:58 Comment(0)
L
12

A couple of points to note

1) You need to be targeting an actual property of Border - You are in effect trying to target the value (DropShadowEffect) of the Effect property, not the property itself.

2) You need to sort the syntax of the PropertyPath.

Change your Storyboard.Target property to the following and you should be fine:

Storyboard.TargetProperty="(Effect).Opacity"

EDIT Working code as noted in comment:

<Border BorderThickness="10" Height="100" Width="100">
    <Border.BorderBrush>
        <SolidColorBrush Color="Red"></SolidColorBrush>
    </Border.BorderBrush>
    <Border.Style>
        <Style TargetType="Border">
            <Style.Resources>
                <Storyboard x:Key="GlowOn">
                    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" 
                          Storyboard.TargetProperty="(Effect).Opacity">
                        <SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="1"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
                <Storyboard x:Key="GlowOff">
                    <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" 
                          Storyboard.TargetProperty="(Effect).Opacity">
                        <SplineDoubleKeyFrame KeyTime="0:0:0.3" Value="0"/>
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </Style.Resources>

            <Setter Property="CornerRadius" Value="6,1,6,1" />
        <!--<Setter Property="BorderBrush"
                    Value="{StaticResource SelectedBorder}" />-->
            <Setter Property="BorderThickness" Value="1" />
        <!--<Setter Property="Background"
                    Value="{StaticResource DeselectedBackground}" />-->
            <Setter Property="RenderTransformOrigin" Value="0.5,0.5" />
        <!--<Setter Property="TextBlock.Foreground"
                    Value="{StaticResource SelectedForeground}" />-->

            <Setter Property="RenderTransform">
                <Setter.Value>
                    <RotateTransform Angle="90"/>
                </Setter.Value>
            </Setter>

            <Setter Property="Effect">
                <Setter.Value>
                    <DropShadowEffect ShadowDepth="20"
                                      BlurRadius="8"
                                      Color="#FFB0E9EF"/>
                </Setter.Value>
            </Setter>

            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">

                    <Trigger.EnterActions>
                        <BeginStoryboard
                              Storyboard="{StaticResource GlowOn}"/>
                    </Trigger.EnterActions>

                    <Trigger.ExitActions>
                        <BeginStoryboard
                              Storyboard="{StaticResource GlowOff}"/>
                    </Trigger.ExitActions>

                </Trigger>
            </Style.Triggers>

        </Style>
    </Border.Style>
</Border>
Leet answered 15/9, 2009 at 6:19 Comment(4)
I get an InvalidOperationException because Effect doesn't have an Opacity property. The value of Effect is DropShadowEffect which has the Opacity property I'm trying to target, but as you point out my XAML is wrong. I've tried setting x:Name on the DropShadowEffect but you can't use TargetName in Styles. There’s a hole in the MSDN documentation about the use of these brackets in storyboards, but I tracked it down in the help for PropertyPath. However I still can't solve the problem. I think I need to cast Effect to DropShadowEffect but this doesn’t seem possible in XAML. Any other ideas?Pernickety
I managed to get the code you have posted working using the syntax I have provided, I did this in a stripped back sample app. I will post what I used and you can maybe work back from that...Leet
Note I have removed the setters which use static resources that you have not provided but that is not going to effect the demonstration. And I notice you are trying to set TextBlock.Foreground property within your style which also will not work.Leet
Correction: You were right after all. I used Blend to generate the Storyboard XAML for me - “Effect.(DropShadowEffect.Opacity)”. I still had problems though. To cut a long story short, I had moved the setter for the Effect to the Trigger at some point, which was the cause of the InvalidOperationException (as the effect wasn’t there when the mouse moved off the border). Moving this setter back into the Style (as I had said in the original post) and it all worked. I then changed the Storyboard to “(Effect).Opacity” as you suggested and it worked. Thanks heaps Simon!Pernickety
S
0

This is a followup to Simon's answer where I have a ListView where the Template item of the ListViewItem had a DropShadow on a Grid. Long story short, because one is overriding the ListViewItem, the selected item and the hover no longer work. To get those to work I had to modify the Opacity and there are two ways to access the Effect depending on where one is; which I show below...here are Full example of the two snippets:

Set during Selection

<ListView.ItemContainerStyle>
    <Style TargetType="ListViewItem">
        <Style.Triggers>
            <Trigger Property="IsMouseOver" Value="True">
                <Setter Property="Cursor" Value="Hand"/>
            </Trigger>

            <MultiTrigger>
                <MultiTrigger.Conditions>
                    <Condition Property="IsSelected" Value="true" />
                    <Condition Property="Selector.IsSelectionActive" Value="true" />
                </MultiTrigger.Conditions>
                <Setter Property="FontWeight" Value="Bold" />
                <Setter Property="Effect">
                    <Setter.Value>
                        <DropShadowEffect Opacity="1"/>
                    </Setter.Value>
                </Setter>
            </MultiTrigger>
        </Style.Triggers>

Set for Grid.Triggers

<Grid Background="GhostWhite">
    <Grid.Effect>
        <DropShadowEffect Opacity="0" />
    </Grid.Effect>
    <GridViewRowPresenter Content="{TemplateBinding Content}"
                      HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                      VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                      SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" />

    <Grid.Triggers>
        <EventTrigger RoutedEvent="MouseEnter">
            <BeginStoryboard>
                    <Storyboard>
                        <DoubleAnimationUsingKeyFrames 
                                        BeginTime="00:00:00"
                                        Storyboard.TargetProperty="(Effect).Opacity">
                            <SplineDoubleKeyFrame KeyTime="0:0:0.1" Value=".2"/>
                            <SplineDoubleKeyFrame KeyTime="0:0:0.4" Value=".6"/>
                            <SplineDoubleKeyFrame KeyTime="0:0:0.6" Value="1"/>
                        </DoubleAnimationUsingKeyFrames>
                    </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
Superfluid answered 29/1, 2020 at 17:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.