wpfanimationresourcedictionarybrushstaticresource

Trying to animate a SolidColorBrush static resource


What I'd like

I want to reuse some styles across multiple UserControl types.

I would like the background of some Border controls to flash, and I'd like them all to use the same style, static resource and animation, so that they all flash in sync.


How I'm trying to do it

To that end, I have defined some common colours in a resource dictionary, like so:

<SolidColorBrush x:Key="StatusErrorBackground" Color="#440000" />

...and I have also defined a StoryBoard in this dictionary, like so:

<Storyboard x:Key="BackgroundAnimation">
    <ColorAnimation
        Storyboard.Target="{StaticResource StatusErrorBackground}"
        Storyboard.TargetProperty="Color"
        From="#440000"
        To="#ff0000"
        Duration="0:0:1"
        RepeatBehavior="Forever"
        AutoReverse="True"/>
</Storyboard>

I've then added the following to a top-level UserControl:

<FrameworkElement.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="CommonResources.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</FrameworkElement.Resources>

<FrameworkElement.Triggers>
    <EventTrigger RoutedEvent="FrameworkElement.Loaded">
        <BeginStoryboard Storyboard="{StaticResource BackgroundAnimation}"/>
    </EventTrigger>
</FrameworkElement.Triggers>

...and then in various other UserControls that are children of that, I re-import the ResourceDictionary as above and use the {StaticResource StatusErrorBackground} for a Background.

The elements in question are coloured red (as in the SolidColorBrush declaration), but they're not flashing.


Fuzzy understanding thus far

Maybe doing this doesn't raise the appropriate PropertyChanged notifications on the elements in question, so they're not redrawn? Or something like that. The Color property on SolidColorBrush isn't a dependency property, but SolidColorBrush implements IAnimatable, so there's obviously magic happening behind the scenes here I don't understand.

Or is it that because I'm importing the same resource dictionary in two different places (once in my top-level UserControl plus once in my child) that I end up with two independent StaticResource references? If you import the same ResourceDictionary file in two different controls, does it create independent resources for each? In which case I might be able to fix this by pulling it in at an app level, I guess...

Can anyone tell me what I doing wrong and how I might go about fixing it?


Solution

  • I can't really say why, but it works if you add a dummy object, e.g. a Rectangle that uses the SolidColorBrush for its Fill property, and then animate that Fill. Now the SolidColorBrush's Color gets animated.

    <SolidColorBrush x:Key="StatusErrorBackground" Color="#440000" />
    <Rectangle x:Key="StatusErrorBackgroundRectangle" Fill="{StaticResource StatusErrorBackground}"/>
    
    <Storyboard x:Key="BackgroundAnimation">
        <ColorAnimation 
            Storyboard.Target="{DynamicResource StatusErrorBackgroundRectangle}" 
            Storyboard.TargetProperty="Fill.(SolidColorBrush.Color)" 
            ... />
    </Storyboard>