The problem I'm having is that if I base a style on a second style that contains a storyboard, then there is an exception in the Trigger.ExitAction.
If I mouse over either of the rectangles in the demo below then the storyboard will run and the rectangles change colour.
When the mouse leaves the red rectangle with style='rectStyle' the storyboard is removed.
When the mouse leaves the blue rectangle (which uses the derived style) I get this exception:
InvalidOperationException:
'MouseOverStoryboard' name cannot be found in the name scope of 'System.Windows.Style'.
So:
Is it valid to have a storyboard in a base style?
Is there a more explicit way of referring to the BeginStoryboardName so that this error doesn't occur?
Any other suggestions?
In the end what I'm trying to achieve re-use a style containing triggers and storyboards in several other styles.
Here's some simple code that demonstrates the problem:
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.Resources>
<Style x:Key="rectStyle" TargetType="{x:Type Rectangle}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard x:Name="MouseOverStoryboard">
<Storyboard>
<ColorAnimation To="PaleGoldenrod"
Storyboard.TargetProperty="(Fill).(Color)"
Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="MouseOverStoryboard"/>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="rectStyle2" TargetType="{x:Type Rectangle}"
BasedOn="{StaticResource rectStyle}"/>
</Grid.Resources>
<Rectangle Grid.Row="0" Width="100" Height="100" Fill="Red"
Style="{StaticResource rectStyle}" />
<Rectangle Grid.Row="1" Width="100" Height="100" Fill="Blue"
Style="{StaticResource rectStyle2}" />
</Grid>
Your best bet is to steer clear of derived styles if you want to include StopStoryboard. There are actually 2 instances of the style and the scope is wrong for the derived style. I believe this is by design. You could abstract that storyboard out to an outer scope in the resources and duplicate the triggers in both styles, referencing the Storyboard by StaticResource. It may not solve your problem since you may have a specific requirement for derived styles, but I don't think you have a choice unfortunately.
Because you cannot inherit from a base style at all if you want to use StopStoryboard you'd have to do something like this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.Resources>
<Storyboard x:Key="mouseOver">
<ColorAnimation
AutoReverse="True"
Duration="0:0:1"
RepeatBehavior="Forever"
Storyboard.TargetProperty="(Fill).(Color)"
To="PaleGoldenrod"/>
</Storyboard>
<Style x:Key="rectStyle" TargetType="{x:Type Rectangle}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard x:Name="MouseOverStoryboard" Storyboard="{StaticResource mouseOver}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="MouseOverStoryboard"/>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="rectStyle2" TargetType="{x:Type Rectangle}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard x:Name="MouseOverStoryboard1" Storyboard="{StaticResource mouseOver}"/>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="MouseOverStoryboard1"/>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
</Grid.Resources>
<Rectangle
Width="100"
Height="100"
Grid.Row="0"
Fill="Red"
Style="{StaticResource rectStyle}"/>
<Rectangle
Width="100"
Height="100"
Grid.Row="1"
Fill="Blue"
Style="{StaticResource rectStyle2}"/>
Just stumbled upon this due to having the same problem. There is another solution, albeit a somewhat clunky one.
Animations on Properties get overwritten when applying another animation, so you can use another BeginStoryboard in the ExitActions of the Trigger to overwrite the previous one, and use a FillBehavior of Stop to automatically remove that.
Unfortunately, the combination of Duration=0, FillBehavior=Stop, and no target value doesn't work, so you need to set a very short duration for that animation.
In your example:
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.Resources>
<Style x:Key="rectStyle" TargetType="{x:Type Rectangle}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<ColorAnimation To="PaleGoldenrod"
Storyboard.TargetProperty="(Fill).(Color)"
Duration="0:0:1"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard FillBehavior="Stop">
<ColorAnimation
Storyboard.TargetProperty="(Fill).(Color)"
Duration="0:0:0.0000001"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>
<Style x:Key="rectStyle2" TargetType="{x:Type Rectangle}"
BasedOn="{StaticResource rectStyle}"/>
</Grid.Resources>
<Rectangle Grid.Row="0" Width="100" Height="100" Fill="Red"
Style="{StaticResource rectStyle}" />
<Rectangle Grid.Row="1" Width="100" Height="100" Fill="Blue"
Style="{StaticResource rectStyle2}" />
</Grid>
Related
here is what im doing
i have a Buttons.xaml style file for styling my menu button
<!-- Menu button -->
<Style x:Key="MenuButton" TargetType="{x:Type Button}">
<Setter Property="Background" Value="{x:Null}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Setter Property="Height" Value="20" />
<Setter Property="Width" Value="50" />
<Setter Property="Margin" Value="0" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="VerticalAlignment" Value="Center" />
<Setter Property="IsHitTestVisible" Value="True" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<Border x:Name="border">
<Grid VerticalAlignment="{TemplateBinding VerticalAlignment}"
HorizontalAlignment="{TemplateBinding HorizontalAlignment}">
<Rectangle x:Name="rectangle" Width="20" Height="2" Fill="{StaticResource DarkGrayBrush}" Margin="0 0 0 0" HorizontalAlignment="Center" VerticalAlignment="Top" RenderTransformOrigin="-0, 0.5" />
<Rectangle x:Name="rectangle1" Width="20" Height="2" Fill="{StaticResource DarkGrayBrush}" Margin="0 5 0 0" HorizontalAlignment="Center" VerticalAlignment="Top" RenderTransformOrigin="-0, 0.5" />
<Rectangle x:Name="rectangle2" Width="20" Height="2" Fill="{StaticResource DarkGrayBrush}" Margin="0 10 0 0" HorizontalAlignment="Center" VerticalAlignment="Top" RenderTransformOrigin="-0, 0.5" />
<ContentPresenter />
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" TargetName="border" Value="{StaticResource FaintWhiteBrush}"/>
</Trigger>
<EventTrigger RoutedEvent="Button.Click" SourceName="menuButton">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="gridMenu" Storyboard.TargetProperty="Width" From="0" To="100" Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="gridMenu" Storyboard.TargetProperty="Width" From="100" To="0" Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
and here is my usercontrol view file
that has menu button itself with the styling and source name in my style that is supposed to be found by my event trigger when this button is clicked and slide out the grid
but its not finding it
<Grid>
<!-- Menu button -->
<Button x:Name="menuButton" Style="{StaticResource MenuButton}" />
<!-- Menu bar -->
<Grid x:Name="gridMenu" Background="White" Width="0" HorizontalAlignment="Left">
</Grid>
when i run this code above this is the error message i get
InvalidOperationException: Cannot find element 'menuButton' targeted by this EventTrigger.
thanks in advance
Triggers inside ControlTemplates (or DataTemplates) can only reference elements that are inside that template. The template doesn't "know" about anything outside of itself, so it can't interact with anything but its own parts.
If you want menuButton to interact with gridMenu, that has to be set up from a context/scope that knows about both of those things. In your case, this would be the UserControl where they are both declared.
If you wanted to implement something like this using an EventTrigger (with XAML only- no code), it would have to be done in the ControlTemplate of the Control that directly contained those two elements. Something like this:
<Control>
<Control.Template>
<ControlTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button Name="menuButton"/>
<Grid Name="gridMenu" Background="Green" Grid.Row="1"/>
</Grid>
<ControlTemplate.Triggers>
<EventTrigger SourceName="menuButton" RoutedEvent="Button.Click">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="gridMenu" Storyboard.TargetProperty="Width" From="0" To="100" Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="gridMenu" Storyboard.TargetProperty="Width" From="100" To="0" Duration="0:0:0.3" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Control.Template>
</Control>
The above is an example showing how to place a trigger in a scope that contains both elements, so that one can affect another. It's not a finished solution, but it should give you an idea of what I mean.
Keep in mind that I've just copy/pasted your EventTriggers into my code. The triggers as you've written them only grow and then immediately shrink menuGrid, which I'm guessing isn't exactly what you want. You probably want it to grow, stay open, and then shrink at some later point. You'll need to work that out on your own (or ask another question), but assuming you want a second click of menuButton to close menuGrid, try using a ToggleButton instead of a normal Button and using EventTriggers in the Checked and Unchecked events.
One last thought: since you're making a UserControl you might want to consider declaring a Boolean property such as IsOpen and using that to trigger the menuGrid animation (via a DataTrigger) instead of having it triggered directly by Button click. This would let you open/close the menu from the Window that is housing the UserControl. All standard controls that have some sort of popup (such as ComboBox and Expander) have some such property that tells you the current state and allows you to change it from the outside.
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!
I've encountered some kind of binding error in my program, which I can't explain by myself.
I wanted to style a TextBox, so that it displays a warning icon if the value is not covered by some product specification. When the user hovers the cursor over the icon, a more detailed warning message should appear in an AdornerLayer.
As you can see, the control works, but I still have a question about it. To describe my problem, I have reduced the code to its absolute minimum:
My code
App.xaml
<Application x:Class="WpfApplication3.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:ThemesAero="clr-namespace:Microsoft.Windows.Themes;assembly=PresentationFramework.Aero"
StartupUri="MainWindow.xaml">
<Application.Resources>
<Style TargetType="{x:Type TextBox}" BasedOn="{StaticResource {x:Type TextBox}}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TextBox}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="22" />
<RowDefinition />
</Grid.RowDefinitions>
<ThemesAero:ListBoxChrome x:Name="Bd" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" RenderMouseOver="{TemplateBinding IsMouseOver}" RenderFocused="{TemplateBinding IsKeyboardFocusWithin}" SnapsToDevicePixels="True">
<ScrollViewer x:Name="PART_ContentHost" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"/>
</ThemesAero:ListBoxChrome>
<Image Name="WarningIcon" Margin="5,0,0,0" Grid.Column="1" RenderOptions.BitmapScalingMode="HighQuality" Source="warning_256x256.png" />
<Border x:Name="InformationBorder" Background="#E1BA18" Margin="5,0,0,0" Grid.Row="1" Grid.ColumnSpan="2" Opacity="0" CornerRadius="1.5" IsHitTestVisible="False" MinHeight="24" MaxWidth="267" VerticalAlignment="Bottom" HorizontalAlignment="Left">
<TextBlock Text="This is some warning message." Foreground="White" Margin="8,3,8,3" TextWrapping="Wrap"/>
</Border>
</Grid>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding ElementName=WarningIcon, Path=IsMouseOver}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="fadeInStoryboard">
<Storyboard>
<DoubleAnimation Duration="00:00:00.15" Storyboard.TargetName="InformationBorder" Storyboard.TargetProperty="Opacity" To="1"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="fadeInStoryboard"/>
<BeginStoryboard x:Name="fadeOutStoryBoard">
<Storyboard>
<DoubleAnimation Duration="00:00:00.15" Storyboard.TargetName="InformationBorder" Storyboard.TargetProperty="Opacity" To="0"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Application.Resources>
</Application>
MainWindow.xaml
<Window x:Class="WpfApplication3.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>
<TabControl>
<TabItem Header="Debug 1">
<TextBox Height="80" Width="150" />
</TabItem>
<TabItem Header="Debug 2">
<TextBox Height="80" Width="150" />
</TabItem>
</TabControl>
</Grid>
</Window>
What is my problem exactly?
What do we have here? I've applied the Style to two TextBoxes in a TabControl.
On the first TabItem (Debug 1), the IsMouseOver trigger works just fine and fades the warning message in and out.
However, an identical TextBox on the second TabItem (Debug 2) throws the following error and the IsMouseOver trigger isn't working at all.
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'ElementName=WarningIcon'. BindingExpression:Path=IsMouseOver; DataItem=null; target element is 'TextBox' (Name=''); target property is 'NoTarget' (type 'Object')
What have I tried to solve the problem?
As I read some suggested solutions on how to fix this, I finally noticed that all of the following triggers are working fine:
<DataTrigger Binding="{Binding ElementName=WarningIcon, Path=IsMouseOver}" Value="True">
<Setter TargetName="InformationBorder" Property="Opacity" Value="1" />
</DataTrigger>
--
<Trigger SourceName="WarningIcon" Property="IsMouseOver" Value="True">
<Trigger.EnterActions>
<BeginStoryboard x:Name="fadeInStoryboard">
<Storyboard>
<DoubleAnimation Duration="00:00:00.15" Storyboard.TargetName="InformationBorder" Storyboard.TargetProperty="Opacity" To="1"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<StopStoryboard BeginStoryboardName="fadeInStoryboard"/>
<BeginStoryboard x:Name="fadeOutStoryBoard">
<Storyboard>
<DoubleAnimation Duration="00:00:00.15" Storyboard.TargetName="InformationBorder" Storyboard.TargetProperty="Opacity" To="0"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
--
<Trigger SourceName="WarningIcon" Property="IsMouseOver" Value="True">
<Setter TargetName="InformationBorder" Property="Opacity" Value="1" />
</Trigger>
This error only occurs when I use a DataTrigger with two Storyboards in a TabControl, but why?
I already know how to fix this, so I'm just interested what's happening behind the scenes.
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.
Well i have a custom control and when Visibility is changed to Visible I have a Trigger with a enter/exit action but the problem is that when the exit action fires the Visibility is no longer Visible so the animation can't be seen how would I fix this?
here is my Trigger:
<ControlTemplate.Triggers>
<Trigger Property="Visibility" Value="Visible">
<Trigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource Hide}"/>
</Trigger.ExitActions>
<Trigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource Show}"/>
</Trigger.EnterActions>
</Trigger>
</ControlTemplate.Triggers>
I tried this too and failed. I think it is not possible to accomplish this in a simple ControlTemplate with a Trigger on the Visibility property. What you can do is add an Opacity animation From 1 To 0 to a Trigger for a different property, for instance a DependencyProperty that you add in the code behind yourself.
You could also use ObjectAnimationUsingKeyFrames to set Visibility for animation period.
In such case there is no need in any codebehind.
There is a way to achieve it. Not 100 % pure, but works for me:
Don't use Visibility property, but use Opacity and Tag property.
<ListView.Resources>
<Style TargetType="{x:Type ListViewItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ListViewItem}">
<Border CornerRadius="5"
BorderThickness="2"
BorderBrush="DodgerBlue"
Background="#CC4f9dea" >
<Grid>
<ContentPresenter HorizontalAlignment="Stretch" SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}" VerticalAlignment="Stretch" />
<Button x:Name="btnClose" Opacity="0" Content="X" Style="{StaticResource RoundedButtonStyle}"/>
</Grid>
</Border>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Tag" TargetName="btnClose" Value="Visible" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListView.Resources>
<Style x:Key="RoundedButtonStyle" TargetType="{x:Type Button}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Button">
<Border CornerRadius="15" Background="White" BorderThickness="1" Padding="2" BorderBrush="Black">
<ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center" />
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
<Style.Triggers>
<Trigger Property="Tag" Value="Visible">
<Trigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="0.0" To="0.5" Duration="0:0:0.5"/>
</Storyboard>
</BeginStoryboard>
</Trigger.EnterActions>
<Trigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetProperty="Opacity"
From="0.5" To="0.0" Duration="0:0:0.5"/>
</Storyboard>
</BeginStoryboard>
</Trigger.ExitActions>
</Trigger>
</Style.Triggers>
</Style>