Specifying PropertyPath syntax for animation inside GroupStyle.HeaderTemplate - wpf

I'm trying to perform a rotate animation inside a GroupStyle header on a DataGrid and I cannot get the PropertyPath syntax down for the Storyboard.TargetProperty property. Here's a contained example to highlight my problem
<Window x:Class="ImageRotateTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<x:Array Type="sys:String">
<sys:String>One</sys:String>
<sys:String>One</sys:String>
<sys:String>Three</sys:String>
<sys:String>Four</sys:String>
<sys:String>Four</sys:String>
</x:Array>
</Window.DataContext>
<Window.Resources>
<CollectionViewSource Source="{Binding}" x:Key="ViewSource">
<CollectionViewSource.GroupDescriptions>
<PropertyGroupDescription></PropertyGroupDescription>
</CollectionViewSource.GroupDescriptions>
</CollectionViewSource>
</Window.Resources>
<DataGrid ItemsSource="{Binding Source={StaticResource ViewSource}}" AutoGenerateColumns="False">
<DataGrid.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}">
<TextBlock.RenderTransform>
<RotateTransform/>
</TextBlock.RenderTransform>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding Name}" Value="Three">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="Test">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="RenderTransform.Angle" To="360" Duration="0:0:0.800" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="Test" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>
</DataTemplate>
</GroupStyle.HeaderTemplate>
</GroupStyle>
</DataGrid.GroupStyle>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding}" Header="Item" />
</DataGrid.Columns>
</DataGrid>
The result here should be that the group header should spin only for the "Three" group and not any others. However, running this results in the following exception
A first chance exception of type 'System.Windows.Markup.XamlParseException' occurred in PresentationFramework.dll
Additional information: Cannot resolve all property references in the property path 'RenderTransform.Angle'. Verify that applicable objects support the properties.
I have tried the following for the Storyboard.TargetProperty without success
(TextBlock.RenderTransform).(RotateTransform.Angle)
(RenderTransform).(Angle)
RenderTransform.Angle
My question is; How can I refer to the TextBlock.RenderTransform using property path syntax?

Your code very nearly works as it is. You just need to make one change:
Storyboard.TargetProperty="RenderTransform.(RotateTransform.Angle)"
I have tested it with just the TextBlock and can see that spinning away, so if you can't see it spinning in your DataGrid, either your Name property Binding is incorrect, or its value is not the expected "Three".
<TextBlock Text="{Binding Name}">
<TextBlock.RenderTransform>
<RotateTransform/>
</TextBlock.RenderTransform>
<TextBlock.Style>
<Style TargetType="TextBlock">
<Style.Triggers>
<DataTrigger Binding="{Binding Name}" Value="Three">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="Test">
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="
RenderTransform.(RotateTransform.Angle)" To="360"
Duration="0:0:0.800" RepeatBehavior="Forever"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="Test" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>

For Rotation of Object this is simple and best example..
<Window x:Class="Animation.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Animated Rectangle" Height="350" Width="525">
<Grid>
<StackPanel Margin="10">
<Image Name="MyImage" Source="e:\a.jpg" Width="100" Margin="50" ></Image>
<Rectangle
Name="MyRectangle"
Width="100"
Height="100"
Fill="Blue">
<Rectangle.Triggers>
<!-- Animates the rectangle's opacity. -->
<EventTrigger RoutedEvent="Rectangle.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="MyImage"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:3"
AutoReverse="True" RepeatBehavior="Forever" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Rectangle.Triggers>
</Rectangle>
</StackPanel>
</Grid>

Related

DoubleAnimation exception when animating grid width with DataTrigger

I'm trying to animate a grid's width upon a toggle button being checked. I've used a data trigger in the Grid's style element to do this, however, whenever it's triggered I get an error, stating:
Cannot animate the 'Width' property on a
'System.Windows.Controls.Grid' using a
'System.Windows.Media.Animation.DoubleAnimation'
I'm pretty sure it is possible to animate the grid in the way I'm attempting, as I've gotten it to work using a click event. Does anyone see where I'm going wrong here?
<Grid Margin="0" HorizontalAlignment="Left"
TextOptions.TextFormattingMode="Display" x:Name="MainGrid" >
<Grid.Resources>
<Style TargetType="Grid">
<Style.Setters>
<Setter Property="Width" Value="300"/>
</Style.Setters>
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsChecked, ElementName=CollapseIcon}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard >
<Storyboard >
<DoubleAnimation Duration="0:0:0.200" Storyboard.TargetProperty="Width" To="16" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
I apologize man, I completely forgot to get back to this Friday and then saw your question again today. Anyway you're so close! Move your dependency property for Width to the object and you're all done! This tested just fine on my end. Cheers!
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid Margin="0" HorizontalAlignment="Left" Width="300" Background="Red"
TextOptions.TextFormattingMode="Display" x:Name="MainGrid" >
<Grid.Resources>
<Style TargetType="Grid">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=IsChecked, ElementName=CollapseIcon}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard >
<Storyboard >
<DoubleAnimation Duration="0:0:0.2"
Storyboard.TargetProperty="Width"
From="300" To="16" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Resources>
</Grid>
<ToggleButton x:Name="CollapseIcon" Content="Magic!" Height="50" Width="50"/>
</Grid>
</Window>
ADDENDUM: Forgot in a DoubleAnim you need to be explicit with both To AND FROM or it just returns NaN in the From by default. Cheers!

Animation inside DataTrigger won't run a second time

This is the code:
<Grid>
<Ellipse Fill="Turquoise" HorizontalAlignment="Left" Height="100" Stroke="Black" VerticalAlignment="Top" Width="100">
<Ellipse.Style>
<Style TargetType="Ellipse">
<Style.Setters>
<Setter Property="Ellipse.RenderTransform">
<Setter.Value>
<TranslateTransform X="0" Y="50"/>
</Setter.Value>
</Setter>
</Style.Setters>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=rectRight, Path=IsMouseOver}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard TargetProperty="RenderTransform.(TranslateTransform.X)">
<!--<DoubleAnimation To="{Binding Path=Width}" Duration="0:0:1"/>--> <!--Doesn't work inside a Style Trigger-->
<DoubleAnimation To="250" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=rectLeft, Path=IsMouseOver}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard TargetProperty="RenderTransform.(TranslateTransform.X)">
<DoubleAnimation To="45" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Bottom" Orientation="Horizontal">
<Rectangle Name="rectLeft" Fill="Gray" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Name="rectRight" Fill="Gray" Height="100" Stroke="Black" Width="100" Margin="10"/>
</StackPanel>
</Grid>
The goal is to animate the Ellipse right when hovering over the right rectangle and left when hovering over the left rectangle. What happens is that after hovering over the left one the Ellipse will no longer move right.
What's also weird is that after changing the order of the DataTrigger declarations around, the reverse is the case.
What's going on that prevents the animation from running again?
I can do this a different way using EventTriggers but in my larger scenario I am using DataTriggers and this is where I am flummoxed.
Another thing is that I wanted to Bind the DoubleAnimation.To property to the Width of the Ellipse but apparently you can't do that in Style DataTriggers and I've yet to find a good workaround. Any help is appreciated.
You need to stop the storyboard before you start other one(add names to both the storyboard & stop each of them before the other runs):
<Grid>
<Ellipse Fill="Turquoise" HorizontalAlignment="Left" Height="100" Stroke="Black" VerticalAlignment="Top" Width="100">
<Ellipse.Style>
<Style TargetType="Ellipse">
<Style.Setters>
<Setter Property="Ellipse.RenderTransform">
<Setter.Value>
<TranslateTransform X="0" Y="50"/>
</Setter.Value>
</Setter>
</Style.Setters>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=rectRight, Path=IsMouseOver}" Value="True">
<DataTrigger.EnterActions>
<StopStoryBoard BeginStoryBoardName="Second"/>
<BeginStoryboard x:Name="First">
<Storyboard TargetProperty="RenderTransform.(TranslateTransform.X)">
<!--<DoubleAnimation To="{Binding Path=Width}" Duration="0:0:1"/>--> <!--Doesn't work inside a Style Trigger-->
<DoubleAnimation To="250" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
<DataTrigger Binding="{Binding ElementName=rectLeft, Path=IsMouseOver}" Value="True">
<DataTrigger.EnterActions>
<StopStoryBoard BeginStoryBoardName="First"/>
<BeginStoryboard x:Name="Second">
<Storyboard TargetProperty="RenderTransform.(TranslateTransform.X)">
<DoubleAnimation To="45" Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Ellipse.Style>
</Ellipse>
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Bottom" Orientation="Horizontal">
<Rectangle Name="rectLeft" Fill="Gray" Height="100" Stroke="Black" Width="100" Margin="10"/>
<Rectangle Name="rectRight" Fill="Gray" Height="100" Stroke="Black" Width="100" Margin="10"/>
</StackPanel>
</Grid>

Open Popup with delay when clicking cell

I want to show a popup with delay 2 seconds always when any cell of a column is selected and the cursor stays longer than 2 seconds. I could implement that with timers and eventhandlers but I think,I can also achieve that with storyboards. I try to do that so:
<Window x:Class="Wpfpopupstoryboard.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<Storyboard x:Key="ShowPopup">
<BooleanAnimationUsingKeyFrames Storyboard.TargetName="LockPopup" Storyboard.TargetProperty="(Popup.IsOpen)">
<DiscreteBooleanKeyFrame KeyTime="00:00:02.0" Value="True" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
<Storyboard x:Key="HidePopup" Storyboard.TargetName="LockPopup" Storyboard.TargetProperty="(Popup.IsOpen)">
<BooleanAnimationUsingKeyFrames>
<DiscreteBooleanKeyFrame KeyTime="00:00:00.1" Value="False" />
</BooleanAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Grid x:Name="LayoutRoot">
<DataGrid Name="MyGrid" xmlns:sys="clr-namespace:System;assembly=mscorlib" IsReadOnly="True">
<DataGrid.Resources>
<Style TargetType="DataGridCell">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="DataGridCell">
<StackPanel>
<Border x:Name="border"
BorderThickness="2"
BorderBrush="Silver">
<ContentPresenter Name="MyContentPresenter" Content="{Binding}"/>
</Border>
<Popup x:Name="LockPopup" PlacementTarget="{Binding ElementName=MyContentPresenter}" Placement="Bottom" DataContext="{Binding}">
<TextBlock Text="This is a popup" Background="White" Foreground="Black" />
</Popup>
</StackPanel>
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="StackPanel.MouseLeftButtonDown">
<BeginStoryboard Storyboard="{StaticResource ShowPopup}"/>
</EventTrigger>
<EventTrigger RoutedEvent="StackPanel.MouseLeave">
<BeginStoryboard Storyboard="{StaticResource HidePopup}"/>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</DataGrid.Resources>
<DataGrid.Columns>
<DataGridTextColumn Binding="{Binding}" Header="column" />
</DataGrid.Columns>
<sys:String>item 1</sys:String>
<sys:String>item 2</sys:String>
<sys:String>item 3</sys:String>
<sys:String>item 4</sys:String>
</DataGrid>
</Grid>
What is wrong? Can somebody help me?
Thank you!
With using RemoveStoryboard action, you need just 1 Storyboard (to show the popup). Also the right event to trigger the Storyboard here is Selected instead of StackPanel.MouseLeftButtonDown:
<ControlTemplate.Triggers>
<EventTrigger RoutedEvent="Selected">
<BeginStoryboard Storyboard="{StaticResource ShowPopup}" Name="bg"/>
</EventTrigger>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard Storyboard="{StaticResource ShowPopup}" Name="bg2"/>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<RemoveStoryboard BeginStoryboardName="bg"/>
</EventTrigger>
</ControlTemplate.Triggers>
You can delete the HidePopup Storyboard, because we don't need it with the code above.
In fact you can also use StackPanel.PreviewMouseLeftButtonDown, somehow the StackPanel.MouseLeftButtonDown is suppressed (while bubbling up from the inner elements). However it's just a bit explanation about why it's not working at first. Using the Selected event is the best choice.
MouseLeftButtonDown event have a Direct Routing strategy (see UIElement.MouseLeftButtonDown Event (msdn)).
So it will not bubble to your ContentTemplate.
You need to set the event trigger on your StackPanel directly.

ComboBox selection change breaks DataTrigger

I am trying to set the selected value of a combobox from a style trigger.It works as long as we dont manually change any value in the combobox.But it stops working altogether after manually changing the selection.How can i solve this.A sample code is attached.Please do help
<Window x:Class="InputGesture.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:InputGesture"
Title="Window2" Height="300" Width="300" Name="Sample">
<Window.Resources>
<Style TargetType="{x:Type ComboBox}">
<Setter Property="ComboBox.SelectedValue" Value="1"/>
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=chk,Path=IsChecked}" Value="True">
<Setter Property="ComboBox.IsEnabled" Value="False"/>
<Setter Property="ComboBox.SelectedValue" Value="2"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<CheckBox Name="chk" Height="23"/>
<ComboBox Name="cmb" Height="23" DisplayMemberPath="Name"
SelectedValuePath="Id" ItemsSource="{Binding ElementName=Sample,Path=DT}">
</ComboBox>
<Button Height="23" Click="Button_Click"/>
</StackPanel>
</Window>
I have found a Quick but Dirty Solutuin i guess..If anyone has a better Idea Please..
<Window x:Class="InputGesture.Window2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:InputGesture"
Title="Window2" Height="300" Width="300" Name="Sample">
<Window.Resources>
<Style TargetType="{x:Type ComboBox}">
<Style.Resources>
<Storyboard x:Key="valueStoryBoard" >
<ObjectAnimationUsingKeyFrames Duration="00:00:00"
FillBehavior="HoldEnd"
Storyboard.TargetProperty="SelectedValue">
<DiscreteObjectKeyFrame KeyTime="00:00:00"
Value="{x:Null}" />
<!--<DiscreteObjectKeyFrame KeyTime="00:00:00"
Value="2" />-->
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</Style.Resources>
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=chk}"
Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="stb" Storyboard="{StaticResource valueStoryBoard}" />
</DataTrigger.EnterActions>
<Setter Property="ComboBox.IsEnabled" Value="False"/>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="stb" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
<StackPanel>
<CheckBox Name="chk" Height="23"/>
<ComboBox Name="cmb" Height="23" DisplayMemberPath="Name"
SelectedValuePath="Id" ItemsSource="{Binding ElementName=Sample,Path=DT}">
</ComboBox>
<Button Height="23" Click="Button_Click"/>
</StackPanel>
</Window>

WPF -- it's gotta be easier than I'm making it

I'm having the darndest time figuring this out: say I've got two Button and three TextBlocks. I want either button to trigger a simple Storyboard on ALL TextBlocks. Currently I'm trying to define a generic Textblock style that contains the Storyboard, and then the trigger comes from any Button click. This is the closest I've come but the app crashes on startup...what am I don't wrong here:
<Window.Resources>
<Style TargetType="TextBlock" >
<Setter Property="Foreground" Value="Blue" />
<Style.Resources>
<Storyboard x:Key="TextBlockOpacity" Storyboard.TargetProperty="Opacity">
<DoubleAnimation From="0" To="1" />
</Storyboard>
</Style.Resources>
</Style>
<Window.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button">
<BeginStoryboard Storyboard="{StaticResource TextBlockOpacity}"/>
</EventTrigger>
</Window.Triggers>
<Grid x:Name="LayoutRoot">
<Button x:Name="button" HorizontalAlignment="Left" Margin="51,54,0,0" VerticalAlignment="Top" Width="96" Height="45" Content="Button"/>
<TextBlock x:Name="textBlock1" Margin="228,54,172,0" VerticalAlignment="Top" Height="45" FontSize="26.667" Text="TextBlock" TextWrapping="Wrap" />
<TextBlock x:Name="textBlock2" Margin="228,103,172,0" VerticalAlignment="Top" Height="45" FontSize="26.667" Text="Hello" TextWrapping="Wrap"/>
</Grid>
If you "dedicate" the button to changing the opacity, you could harness its DataContext and animate it. Then simply bind your elements' Opacity to the DataContext:
(I've also refactored your xaml a bit)
<Window x:Class="SomeNamespace.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:System="clr-namespace:System;assembly=mscorlib"
Title="Window1" Height="300" Width="300">
<Window.Resources>
<Storyboard x:Key="TextBlockOpacity" Storyboard.TargetName="button1" Storyboard.TargetProperty="DataContext" >
<DoubleAnimation From="0.1" To="1"/>
</Storyboard>
<Style TargetType="TextBlock" >
<Setter Property="Foreground" Value="Blue" />
<Setter Property="Background" Value="LightGray" />
<Setter Property="FontSize" Value="26.667" />
<Setter Property="TextWrapping" Value="Wrap" />
<Setter Property="Height" Value="45" />
<Setter Property="Opacity" Value="{Binding ElementName=button1, Path=DataContext}"/>
</Style>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click">
<BeginStoryboard Storyboard="{StaticResource TextBlockOpacity}" >
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="ListBox.SelectionChanged">
<BeginStoryboard Storyboard="{StaticResource TextBlockOpacity}" >
</BeginStoryboard>
</EventTrigger>
</Window.Triggers>
<Grid x:Name="LayoutRoot">
<Button x:Name="button1" HorizontalAlignment="Left" Margin="51,54,0,0" VerticalAlignment="Top" Width="96" Height="45" Content="Button">
<Button.DataContext>
<System:Double>0</System:Double>
</Button.DataContext>
</Button>
<Button x:Name="button2" HorizontalAlignment="Right" Margin="0,54,29,0" VerticalAlignment="Top" Width="96" Height="45" Content="Button"/>
<ListBox x:Name="listBox1" Height="50" VerticalAlignment="Top">
<ListBox.Items>
<System:String>Text1</System:String>
<System:String>Text2</System:String>
</ListBox.Items>
</ListBox>
<TextBlock x:Name="textBlock1" Margin="51,114,61,0" Text="TextBlock" Height="45" VerticalAlignment="Top" Width="166" />
<TextBlock x:Name="textBlock2" Margin="51,0,74,42" Text="Hello" Height="45" Width="153" VerticalAlignment="Bottom" />
</Grid>
</Window>
Also note one thing - this is the approach to use if you want to minimize your code, and make it all happen in xaml. Your approach would anmate the Opacity of the whole Window. That's why in the code above, TextBlocks bind to the button's DataContext, which is itself animated.
It is of course doable without binding to a common value (the DataContext), but then you need to repeat X animations (because you need to set X TargetNames). This approach above is more easily extendable and maintainable.
EDIT
Added another Button and a ListBox for variety :)
Based on kek444's Xaml-only solution, I present a slightly improved version that doesn't rely on the DataContext of the button and can have multiple triggers.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="WpfApplication1.MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Window.Resources>
<UIElement x:Key="OpacityCounter" Opacity="0"/>
<Style TargetType="TextBlock">
<Setter Property="Opacity" Value="{Binding Source={StaticResource OpacityCounter}, Path=Opacity}" />
</Style>
<Storyboard x:Key="OnClick1">
<DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.Target="{StaticResource OpacityCounter}" Storyboard.TargetProperty="(UIElement.Opacity)">
<SplineDoubleKeyFrame KeyTime="00:00:00" Value="0"/>
<SplineDoubleKeyFrame KeyTime="00:00:00.5000000" Value="1"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<Window.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button1">
<BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
</EventTrigger>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button2">
<BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
</EventTrigger>
</Window.Triggers>
<Grid x:Name="LayoutRoot">
<StackPanel>
<StackPanel Orientation="Horizontal">
<Button x:Name="button1" Width="131" Height="37" Content="Button 1" Margin="0,0,0,22"/>
<Button x:Name="button2" Width="131" Height="37" Content="Button 2" Margin="0,0,0,22"/>
</StackPanel>
<TextBlock x:Name="textBlock" Height="27" Text="TextBlock 1" TextWrapping="Wrap" />
<TextBlock x:Name="textBlock1" Height="27" Text="TextBlock 2" TextWrapping="Wrap" />
<TextBlock x:Name="textBlock2" Height="27" Text="TextBlock 3" TextWrapping="Wrap" />
<TextBlock x:Name="textBlock3" Height="27" Text="TextBlock 4" TextWrapping="Wrap" />
</StackPanel>
</Grid>
</Window>
To use a ListBox as a trigger mechanism (provided you have a ListBox named "listbox1" someplace, add the following to Window.Triggers:
<EventTrigger RoutedEvent="Selector.SelectionChanged" SourceName="listbox1">
<BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
</EventTrigger>
or to trigger off a specific ListBoxItem, you'll need (where item1 is a named ListBoxItem):
<EventTrigger RoutedEvent="ListBoxItem.Selected" SourceName="item1">
<BeginStoryboard Storyboard="{StaticResource OnClick1}"/>
</EventTrigger>
In your sample, you are defining the Storyboard inside a Style as a Resource, but then you are trying to access it as a Window resource. Try moving the Storyboard declaration to Window.Resources, then reference the Storyboard in the Style.
I don't know right off if it will do what you want, but I would start there.

Resources