Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

define animations and triggers as reusable resource?

Is there a way to define an animation somewhere in xaml (eg. as a resource) once and then reuse it multiple times? I have a lot of independent brushes across differnt datatemplates that independently need to start the same kind of animation based on a datatrigger. Now since it seems that an animation has to define an Storyboard.TargetName and Storyboard.TargetProperty. This pretty much defeats the purpose of reusability. I would somehow like to declare "use this animation form the resource but apply it to another element this time".

To me this seems to be a rather basic, important and essential request and I am suprised that its not that straight forward to acomplish. Am I missing something here?

The same thing applies for triggers. Suppose I have a lot of differnt visual elements that all represent the same type of state using color animations. E.g. fade to green when "active" fade to "red" when "error" etc. The only difference between the visuals is their shape/visual tree the desired animation behavior is the same, they all have an element somewhere in their visual tree that has a property of type color. I think it is not hard to imagine how tedious it is to redefine the same animations and datatrigger sets over and over again. Every developer hates this. I desperately seek for an easier solution that doesn't require no (or at least very little) c# code behind.

What I have come up with so far is this:

Define the animations in a resource lik this (repeat this for all basic states that there are, like activating, active, inactive, error):

<ColorAnimationUsingKeyFrames x:Key="deactivatingColorAnimation" 
                    Storyboard.TargetProperty="Material.(MaterialGroup.Children)[0].Brush.(SolidColorBrush.Color)"                    
                    FillBehavior="HoldEnd" RepeatBehavior="Forever" AutoReverse="True">
      <ColorAnimationUsingKeyFrames.KeyFrames>
        <LinearColorKeyFrame KeyTime="00:00:00" Value="Gray"/>
        <LinearColorKeyFrame KeyTime="00:00:0.25" Value="Gray"/>
        <LinearColorKeyFrame KeyTime="00:00:0.5" Value="Gray" />
        <LinearColorKeyFrame KeyTime="00:00:0.75" Value="Gray" />
     </ColorAnimationUsingKeyFrames.KeyFrames>
</ColorAnimationUsingKeyFrames>

The use it in storyboard in the triggers (repeat this zillions of times for each state X each differnt stateviusal, always come up with a new name for the storyboard):

<DataTrigger Binding="{Binding SubstrateHolder.State}" Value="Deactivating">
        <DataTrigger.EnterActions>
            <BeginStoryboard x:Name="someStateVisualDeactivatingStoryboard">
                <Storyboard Storyboard.TargetName="someStateVisual">
                    <StaticResource ResourceKey="deactivatingColorAnimation" />
                </Storyboard>
            </BeginStoryboard>
        </DataTrigger.EnterActions>
        <DataTrigger.ExitActions>
            <RemoveStoryboard BeginStoryboardName="someStateVisualDeactivatingStoryboard" />
        </DataTrigger.ExitActions>
</DataTrigger>

You can easily imagine how much bloat XAML I have to repeatedly copy and paste for all those zillion DataTriggers.

It would be cool to define all this triggers once and apply it to different state visuals. How is something like this solved in WPF? Any tip?

like image 985
bitbonk Avatar asked Oct 31 '09 13:10

bitbonk


1 Answers

Could you try something like this?

  • Wrap all your current control templates with an invisible root element, e.g. a Border or a StackPanel, whose bounding box will cover the entire control.
  • Create a style or control template for this invisible box that contains all your triggers and animations.
  • Have the animations animate an arbitrary Color property on the invisible box.
  • In the visual trees for all your different controls, bind any properties you want to animate to the Color property on the invisible root element.
like image 136
Dewb Avatar answered Oct 21 '22 02:10

Dewb