A question appeared on StackOverflow asking how to animate a property on multiple elements from one or more trigger mechanisms (i.e. a button click or list box selection).  The traditional approach (for brevity’s sake, I omitted the Xaml comprising the actual UI elements) is rather straight-forward:

<Window.Resources>
<Storyboard x:Key="OnClick1">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="textBlock1"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="textBlock2"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="textBlock3"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.TargetName="textBlock4"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard> <Window.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button">
<BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
</EventTrigger>
</Window.Triggers>
</Window.Resources>

 
The major complaint about the above solution is the repetition of the Animations.  Since each TextBlock implements the same animation, an easier to maintain solution would be ideal.  Initially, I believed a Xaml-only solution would not be possible, but StackOverflow user, kek444, put me onto a simple trick of animating a single value and DataBinding the TextBlocks to it.  While his solution involved setting the DataContext on an element, I believe using a placeholder element is a cleaner approach (however, I’m sure this is open to debate).
 
The updated version of the above Xaml would look as follows:

<Window.Resources>
<UIElement x:Key="AnimationPlaceholder" Opacity="0"/> <Style TargetType="TextBlock">
<Setter Property="Opacity"
Value="{Binding Source={StaticResource AnimationPlaceholder}, Path=Opacity}" />
</Style>

<Storyboard x:Key="OnClick1">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00"
Storyboard.Target="{StaticResource AnimationPlaceholder}"
Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>

<Window.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button">
<BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
</EventTrigger>
</Window.Triggers>
</Window.Resources>

In this snippet, I’m using a UIElement to hold the animation value since it supports the Opacity property (but in fact, any property of type double, would suffice).  Also, if you’re not adverse to a little coding, a custom class could be created to contain the values you wish to change for a particular animation.  A style is created to affect all TextBoxes, but this can easily be modified to use explicit styling.  Finally, the Storyboard targets the placeholder object and changes its value from 0 to 1 over 0.5 seconds.  The style uses DataBinding to bind its Opacity property to the placeholder’s.

Though Blend creates a lot of the Xaml for you when creating trigger-based animations, sometimes the result can be less than ideal.  Additionally, as I’ve had reinforced through this little exercise, there is more than one way to skin a cat when it comes to Xaml, so please feel free to comment with refinements or alternative solutions.