WPF Animation : How do i make it slide in? - c#

So I just got into animations and I wanted to do a "Slide out" animation and I managed to do so just fine.
But now I want it to slide in with the click on the same button.
So like I click it and it slides out and then I want it to slide back in when I click it again.
WITHOUT any code behind, so just through xaml
Here is the XAML
<Grid>
<Grid.Resources>
<Storyboard x:Key="TransformImage">
<DoubleAnimation
Storyboard.TargetName="MovingImage"
Storyboard.TargetProperty="(Image.RenderTransform).(TranslateTransform.X)"
By="130" Duration="0:0:0.3">
</DoubleAnimation>
</Storyboard>
<Storyboard x:Key="TransformButton">
<DoubleAnimation
Storyboard.TargetName="btnChange"
Storyboard.TargetProperty="(Button.RenderTransform).(TranslateTransform.X)"
By="130" Duration="0:0:0.3">
</DoubleAnimation>
</Storyboard>
</Grid.Resources>
<Grid.Triggers>
<EventTrigger RoutedEvent="Button.Click" SourceName="btnChange">
<BeginStoryboard Storyboard="{StaticResource TransformImage}"/>
<BeginStoryboard Storyboard="{StaticResource TransformButton}"/>
</EventTrigger>
</Grid.Triggers>
<StackPanel Orientation="Horizontal" Margin="0">
<Image x:Name="MovingImage" Source="logo.png"
MaxWidth="120">
<Image.RenderTransform>
<TranslateTransform />
</Image.RenderTransform>
</Image>
</StackPanel>
<StackPanel
Panel.ZIndex="1"
Height="450"
Width="120"
HorizontalAlignment="Left"
Background="Black"></StackPanel>
<Button Margin="130,0,0,0" Height="40" Width="120"
Content="Show Image" x:Name="btnChange"
HorizontalAlignment="Left" >
<Button.RenderTransform>
<TranslateTransform />
</Button.RenderTransform>
</Button>
</Grid>

You need to store current state of slide animation when clicking on button and based on it run appropriate story board.
For example, you could use ToggleButton that has IsChecked property (or property in view-model).
To avoid duplicate triggers/styles I placed Image and ToggleButton in the same StackPanel.
<Grid>
<Grid.Resources>
<system:Double x:Key="SlideOffSet">130</system:Double>
<Storyboard x:Key="SlideRight">
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)"
From="0" To="{StaticResource SlideOffSet}"
Duration="0:0:0.3" />
</Storyboard>
<Storyboard x:Key="SlideLeft">
<DoubleAnimation Storyboard.TargetProperty="(UIElement.RenderTransform).(TranslateTransform.X)"
From="{StaticResource SlideOffSet}" To="0"
Duration="0:0:0.3" />
</Storyboard>
</Grid.Resources>
<StackPanel Orientation="Horizontal" Margin="0">
<StackPanel.Style>
<Style TargetType="StackPanel">
<Style.Triggers>
<DataTrigger Binding="{Binding IsChecked, ElementName=SlideState}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource SlideRight}" />
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard Storyboard="{StaticResource SlideLeft}" />
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</StackPanel.Style>
<StackPanel.RenderTransform>
<TranslateTransform />
</StackPanel.RenderTransform>
<Image Source="logo.png" MaxWidth="120" />
<ToggleButton x:Name="SlideState" Margin="10,0,0,0" Height="40" Width="120" Content="Show Image" />
</StackPanel>
<StackPanel
Panel.ZIndex="1"
Height="450"
Width="120"
HorizontalAlignment="Left"
Background="Black"></StackPanel>
</Grid>
Also, I would not recommend using By property of the DoubleAnimation:
If animation is still running and you click button again, then second animation will be started at wrong position (it will use X value from first animation, which is not finished) - Click button quickly many times and you will see the problem.
Use From and To properties instead.

Related

Event triggered only when a condition occurs

what I'm trying to do is basically set a condition for an event to be triggered. I have this custom control where there is a Grid that has the following behavior:
MouseOver: the Opacity of another Grid (from now on called priorityFlag and placed over the triggered one, called priorityGrid) is set from 0 to 100 and its Width is set from 10 to 20.
MouseLeave: the Opacity of the priorityFlag is set back to 0 and its Width back to 10.
MouseUp: the user clicks on one of the priorityFlag's rows and, through a command, it changes the color of the priorityGrid. When the click ends, the priorityFlag's Opacity goes to 0 and its Width is set back to 10 (basically the same behavior of the MouseLeave event).
It works just fine, but when the MouseUp occurs and the user leaves the priorityGrid, the MouseLeave event gets triggered and I obtain the following behavior (you can see me hovering a couple times over the priorityGrid and then changing the priority color):
As you can see, there is an annoying flickering effect caused by the MouseLeave event.
What I'd like to know is: can I condition a trigger in order to avoid the properties changes? It seems to me that there is no parameter allowing me to do so...
Here is the custom control XAML code:
<UserControl x:Class="CSB.Tasks.TaskListItemControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:CSB.Tasks"
xmlns:core="clr-namespace:CSB.Tasks.Core;assembly=CSB.Tasks.Core"
mc:Ignorable="d"
d:DesignHeight="70"
d:DesignWidth="400">
<!-- Custom control that represents a Task. -->
<UserControl.Resources>
<!-- The control style. -->
<Style x:Key="ContentStyle"
TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<Border x:Name="ContainerBorder"
BorderBrush="{StaticResource LightVoidnessBrush}"
Background="{StaticResource VoidnessBrush}"
BorderThickness="1"
Margin="2">
<Border.InputBindings>
<MouseBinding MouseAction="LeftClick"
Command="{Binding SelectTaskCommand}"/>
</Border.InputBindings>
<!-- The grid that contains the control. -->
<Grid Name="ContainerGrid"
Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<!-- Border representing the priority state of the Task:
The color is defined by a ValueConverter according to the PriorityLevel of the Task object. -->
<Border Grid.Column="0"
Name="priorityFlag"
Width="10"
HorizontalAlignment="Left"
Background="{Binding Priority, Converter={local:PriorityLevelToRGBConverter}, FallbackValue={StaticResource EmerlandBrush}}">
<Grid Name="priorityGrid"
Opacity="0"
HorizontalAlignment="Left"
Width="20">
<Grid.RowDefinitions>
<RowDefinition/>
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Grid.Row="0"
Name="lowPriority"
Background="{Binding Source={x:Static core:PriorityLevel.Low}, Converter={local:PriorityLevelToRGBConverter}}">
<Border.InputBindings>
<MouseBinding MouseAction="LeftClick"
Command="{Binding SetLowPriorityCommand}"/>
</Border.InputBindings>
</Border>
<Border Grid.Row="1"
Name="mediumPriority"
Background="{Binding Source={x:Static core:PriorityLevel.Medium}, Converter={local:PriorityLevelToRGBConverter}}">
<Border.InputBindings>
<MouseBinding MouseAction="LeftClick"
Command="{Binding SetMediumPriorityCommand}"/>
</Border.InputBindings>
</Border>
<Border Grid.Row="2"
Name="highPriority"
Background="{Binding Source={x:Static core:PriorityLevel.High}, Converter={local:PriorityLevelToRGBConverter}}">
<Border.InputBindings>
<MouseBinding MouseAction="LeftClick"
Command="{Binding SetHighPriorityCommand}"/>
</Border.InputBindings>
</Border>
<Grid.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="priorityGrid" Storyboard.TargetProperty="Opacity" From="0" To="100" Duration="0:0:0:0.1"/>
<DoubleAnimation Storyboard.TargetName="priorityFlag" Storyboard.TargetProperty="Width" From="10" To="20" Duration="0:0:0:0.1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="priorityGrid" Storyboard.TargetProperty="Opacity" From="100" To="0" Duration="0:0:0:0.1"/>
<DoubleAnimation Storyboard.TargetName="priorityFlag" Storyboard.TargetProperty="Width" From="20" To="10" Duration="0:0:0:0.1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseUp">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Storyboard.TargetName="priorityGrid" Storyboard.TargetProperty="Opacity" From="100" To="0" Duration="0:0:0:0.1"/>
<DoubleAnimation Storyboard.TargetName="priorityFlag" Storyboard.TargetProperty="Width" From="20" To="10" Duration="0:0:0:0.1"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
</Grid>
</Border>
<!-- Border containing the Task's informations. -->
<Border Grid.Column="0"
Margin="20 0 0 0"
Padding="5">
<StackPanel>
<!-- The title of the Task. -->
<TextBlock Text="{Binding Title}"
FontSize="{StaticResource TaskListItemTitleFontSize}"
Foreground="{StaticResource DirtyWhiteBrush}"/>
<!-- The customer the Taks refers to. -->
<TextBlock Text="{Binding Customer}"
Style="{StaticResource TaskListItemControlCustomerTextBlockStyle}"/>
<!-- The description of the Task. -->
<TextBlock Text="{Binding Description}"
TextTrimming="WordEllipsis"
Foreground="{StaticResource DirtyWhiteBrush}"/>
</StackPanel>
</Border>
<!-- Border that contains the controls for the Task management. -->
<Border Grid.Column="2"
Padding="5">
<!-- Selection checkbox of the Task. -->
<CheckBox VerticalAlignment="Center"
IsChecked="{Binding IsSelected}"/>
</Border>
</Grid>
</Border>
<!-- Template triggers. -->
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding IsSelected}" Value="True">
<Setter Property="Background" TargetName="ContainerBorder" Value="{StaticResource OverlayVoidnessBrush}"/>
<Setter Property="BorderBrush" TargetName="ContainerBorder" Value="{StaticResource PeterriverBrush}"/>
</DataTrigger>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0:0" To="{StaticResource OverlayVoidness}" Storyboard.TargetName="ContainerGrid" Storyboard.TargetProperty="Background.Color"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<ColorAnimation Duration="0:0:0:0" To="Transparent" Storyboard.TargetName="ContainerGrid" Storyboard.TargetProperty="Background.Color"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</UserControl.Resources>
<!-- Content of the control: assignment of the DataContext for design-time testing. -->
<ContentControl d:DataContext="{x:Static local:TaskListItemDesignModel.Instance}"
Style="{StaticResource ContentStyle}"/>
Can anyone help me? Thank you in advance for the help.
It looks like that when you trigger the MouseUp trigger it also triggers the MouseOver trigger. Therefore, the priorityFlag's Width is changed to 20 twice during the same time. Obviously, it is twice changed back,when you move the Mouse away, once (i) via MouseLeave and once (ii) via MouseUp end of the click, also basically during the same time, which causes the flickering.
You may define a private flag property in the class containing all the mouse events, which would be set to true, when the priorityFlag's Width is set to 20 and test the flag before you set it to 20 again. Or you just test the current Width before you change it in any mouse triggered event.

Animation(move Image) to right edge of Canvas

I have a page,page have canvas,in canvas exist image,and exist animation.
Animation(beginning on datatrigger) must move image from Canvas.Left to ActualWidth of Canvas.
It's easy at first sight :) but...
Binding don't wokring,im trying to solve this for 2 days (((
I have two solutions for this problem, but none is complete.
Solution 1: DataTrigger - Working. Binding "To" - Don't woking.
<ContentControl>
<ContentControl.Template>
<ControlTemplate TargetType="ContentControl">
<ControlTemplate.Resources>
<Storyboard x:Key="EnemyAnimation" Storyboard.TargetName="Xenomorph" Storyboard.TargetProperty="(Canvas.Left)">
<DoubleAnimation From="0" To="{Binding ElementName=Canvas1,Path=ActualWidth}" BeginTime="0:0:3" Duration="0:0:10" />
</Storyboard>
</ControlTemplate.Resources>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding startAi}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard Storyboard="{StaticResource EnemyAnimation}" />
</DataTrigger.EnterActions>
</DataTrigger>
</ControlTemplate.Triggers>
<Canvas x:Name="Canvas1" Margin="20" Grid.Row="1">
<Image x:Name="Xenomorph1" Height="100" Width="100" VerticalAlignment="Center" Source="/Mathilvania;component/Resources/Xenomorph.gif" HorizontalAlignment="Center" Margin="10,65,0,0" Grid.Row="1"/>
</Canvas>
</ControlTemplate>
</ContentControl.Template>
</ContentControl>
Solution 2: DataTrigger - I can't add DataTrigger. Binding "To" - Working
<Canvas Name="canv" Margin="50,0,100,0" Grid.Row="1" VerticalAlignment="Center" Height="100">
<Image x:Name="Xenomorph" Height="100" Width="100" VerticalAlignment="Center" Source="/Mathilvania;component/Resources/Xenomorph.gif" HorizontalAlignment="Center" Margin="0" Grid.Row="1"/>
<Canvas.Triggers>
<EventTrigger RoutedEvent="Canvas.SizeChanged">
<BeginStoryboard>
<Storyboard TargetName="Xenomorph">
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)"
BeginTime="0:0:1"
Duration="0:0:5"
From="0"
To="{Binding ElementName=canv, Path=ActualWidth}" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Canvas.Triggers>
</Canvas>
In Solution 1,i can't Binding "To" but trigger working.In solution 2 Binding work,but DataTrigger,i can't add
UPDATE:
When i add DataTrigger to Solution2 like this:
<Canvas Name="canv" Margin="50,0,100,0" Grid.Row="1" VerticalAlignment="Center" Height="100">
<Image x:Name="Xenomorph" Height="100" Width="100" VerticalAlignment="Center" Source="/Mathilvania;component/Resources/Xenomorph.gif" HorizontalAlignment="Center" Margin="0" Grid.Row="1"/>
<Canvas.Triggers>
<DataTrigger Binding="{Binding startAi}" Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard TargetName="Xenomorph">
<DoubleAnimation Storyboard.TargetProperty="(Canvas.Left)"
BeginTime="0:0:1"
Duration="0:0:5"
From="0"
To="{Binding ElementName=canv, Path=ActualWidth}" />
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Canvas.Triggers>
I have an erron:
Elements of the Triggers family must have the type EventTrigger
This is a pretty common problem. You can use the data bindings for the From and To properties of an animation only if it is not in an ControlTemplate or a Style. In these cases, the Animation needs to be sealed (frozen), that's obviously not possible if some its properties change their values dynamically.
There is a workaround solution for this. It isn't neat, but it works. You just have to introduce an intermediate scale factor that you'll be animating with a hard-coded Animation. But the actual value will be then calculated using a multiplying IMultiValueConverter on a MultiBinding.
Here is an example.
The converter could look like this:
public class MultiplyConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
return values.OfType<double>().Aggregate(1.0, (current, t) => current * t);
}
// ConvertBack omitted...
}
And in XAML, you can use the Tag of your object for holding the animated scale factor.
Something like this:
<Canvas x:Name="Canvas" xmlns:l="Your_converter_namespace" xmlns:sys="clr-namespace:System;assembly=mscorlib">
<Canvas.Resources>
<l:MultiplyConverter x:Key="MultiplyConverter"/>
</Canvas.Resources>
<Rectangle Height="100" Width="100" Fill="Blue">
<Rectangle.Style>
<Style TargetType="Rectangle">
<Style.Triggers>
<DataTrigger Binding="{Binding IsAnimationStarted}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard x:Name="Storyboard1">
<Storyboard TargetProperty="Tag">
<DoubleAnimation From="0" To="1" Duration="0:0:5"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<StopStoryboard BeginStoryboardName="Storyboard1"/>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
</Rectangle.Style>
<Rectangle.Tag>
<sys:Double>0</sys:Double>
</Rectangle.Tag>
<Canvas.Left>
<MultiBinding Converter="{StaticResource MultiplyConverter}">
<Binding Path="ActualWidth" ElementName="Canvas"/>
<Binding Path="Tag" RelativeSource="{RelativeSource Self}"/>
</MultiBinding>
</Canvas.Left>
</Rectangle>
</Canvas>
You'll see that resizing the Canvas won't cause the animation to start over again, but rather it will seamlessly continue.

How to make animation start at hovering - storyboard

How to make the animation start of the TextBlock when entering (hovering) the button
In TextBlock I want that the <EventTrigger RoutedEvent will be in Input2 at MouseEnter, How can I do that
<EventTrigger RoutedEvent=Input2.MouseEnter doesn't recognized
The button:
<Button Grid.Row="0" Name="Input2" Click="Input_Click" MouseEnter="Input_MouseEnter" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="{x:Null}">
<Button.Template>
<ControlTemplate>
<Border HorizontalAlignment="Center" VerticalAlignment="Center" >
<Image Source= "C:\Users\Me\input.png"
Width="40"
Height="40"/>
</Border>
</ControlTemplate>
</Button.Template>
</Button>
The TextBlock:
<TextBlock Grid.Row="0" Name="Input_Name1" Text="Input" FontSize="40" FontFamily="/10KHours;component/Font_count/#Dancing Script" VerticalAlignment="Center" Height="48" Margin="65.346,33.6,-102.081,36">
<TextBlock.Triggers>
<EventTrigger RoutedEvent="TextBlock.Loaded">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetName="Input_Name1"
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:5"
AutoReverse="true" RepeatBehavior="1x">
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</TextBlock.Triggers>
</TextBlock>
The basic idea to change the style of the TextBlock is totally correct. Add a DataTrigger and bind it to the the IsMouseOver of the Button you are going to hover. Using the IsMouseOver is propaply the simplest way to get the desired information. Here is a minimal example:
<Button x:Name="btn" Content="Hover me"/>
<TextBlock x:Name="tb" Text="Input">
<TextBlock.Style>
<Style TargetType="{x:Type TextBlock}">
<Style.Triggers>
<DataTrigger Binding="{Binding ElementName=btn, Path=IsMouseOver}" Value="True">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation
Storyboard.TargetProperty="Opacity"
From="1.0" To="0.0" Duration="0:0:1"
AutoReverse="true" RepeatBehavior="1x">
</DoubleAnimation>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
</DataTrigger>
</Style.Triggers>
</Style>
</TextBlock.Style>
</TextBlock>

WPF: Change visiable of Label when other control click

I just go to WPF and have many problems, I very much like WPF and started working with it. I just make a design with WPF:
Now, I want when I click on label (icon with 3 line), then label without icon in sidebar will hide (can hide with animation).
Here my code:
Icon button:
<DockPanel DockPanel.Dock="Left">
<!-- Minimize Sidebar -->
<Label Name="LblMinimizeSideBar" Style="{StaticResource FontAwesome}" Foreground="{DynamicResource MainColor}" FontSize="24" Margin="10 0 0 0" VerticalAlignment="Center" MouseLeftButtonDown="LblMinimizeSideBar_MouseLeftButtonDown"></Label>
</DockPanel>
Sidebar:
<StackPanel DockPanel.Dock="Left" Width="80" Background="{DynamicResource MainColor}">
<ItemsControl Name="IcTodoList">
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel IsEnabled="{Binding IsEnabled}" Orientation="Vertical" Background="{Binding Background}" SnapsToDevicePixels="True" Cursor="Hand">
<Label Style="{StaticResource FontAwesome}" HorizontalAlignment="Center" FontSize="20" Foreground="#FFF">

</Label>
<Label HorizontalAlignment="Center" Foreground="#FFF" Padding="0 0 0 10" Content="{Binding Title}"></Label>
<StackPanel.Triggers>
<EventTrigger RoutedEvent="MouseEnter">
<BeginStoryboard>
<Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(StackPanel.Background).Color">
<LinearColorKeyFrame Value="#DB1918" KeyTime="0:0:0.6"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="MouseLeave">
<BeginStoryboard>
<Storyboard>
<ColorAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetProperty="(StackPanel.Background).Color">
<LinearColorKeyFrame Value="#FF5750" KeyTime="0:0:0.6"/>
</ColorAnimationUsingKeyFrames>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</StackPanel.Triggers>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
Any easy way to make this?
Thankyou very much!
you can use this in the label triggers to start animation in the items control
Example
<ItemsControl Name="TheItemYouWantToChange" />
in the view resources
<!-- Begin the Storyboard -->
<EventTrigger RoutedEvent="Button.Click\MOUSEDOWN" SourceName="YOUR_LABLE\BUTTON_NAME">
<BeginStoryboard Name="MyBeginStoryboard">
<Storyboard >
<DoubleAnimation
Storyboard.TargetName="TheItemYouWantToChange"
Storyboard.TargetProperty="Opacity"
Duration="0:0:5" From="1" To="0" />
</Storyboard>
</BeginStoryboard>
</EventTrigger>
you can use animation to change opacity and visibility
for more info you can see : (the example is partly from there) http://msdn.microsoft.com/en-us/library/ms744905(v=vs.110).aspx

Animate control based on other control

I am creating a media player application and I am trying to animate hiding the controls when the mouse is not inside the program window.
I have a animation setup and working, but I can't think of how to set the EventTrigger to the parent grid rather than the grid I actually want to animate. Essentially I want to set the EventTrigger to be grdMain and animate the height of grdControls.
Animation:
<Window.Resources>
<Style x:Key="FadeInOut" TargetType="Grid">
<Style.Triggers>
<EventTrigger RoutedEvent="Control.MouseEnter">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:1" To="40" Storyboard.TargetProperty="Height"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Control.MouseLeave">
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:1" To="0" Storyboard.TargetProperty="Height"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Style.Triggers>
</Style>
</Window.Resources>
Grids:
<Grid x:Name="grdMain" Background="Black">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<MediaElement x:Name="meVideo" IsMuted="True" Stretch="Uniform" MediaOpened="meVideo_MediaOpened" MediaEnded="meVideo_MediaEnded" Grid.RowSpan="2" />
<Grid Grid.Row="1" >
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ProgressBar x:Name="pgbVideoTimeline" HorizontalAlignment="Stretch" Height="7" Background="#252525" Foreground="Maroon" BorderThickness="0" Grid.Row="1" MouseDown="pgbVideoTimeline_MouseDown" MouseMove="pgbVideoTimeline_MouseMove" MouseUp="pgbVideoTimeline_MouseUp" />
<Grid x:Name="grdControls" Grid.Row="2" Background="#0C0D0D" Height="0" Style="{StaticResource FadeInOut}" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<StackPanel x:Name="stpPlaybackControls" Orientation="Horizontal" HorizontalAlignment="Left" Grid.Column="0">
<Image x:Name="btnPlayPause" Height="30" Margin="10,0,5,0" ToolTip="Play" Source="Resources/Images/UI/Play.png" MouseEnter="btnVideoControl_MouseEnter" MouseLeave="btnVideoControl_MouseLeave" MouseUp="btnPlayPause_MouseUp" />
<Image x:Name="btnReplay" Height="20" Margin="5,0,5,0" ToolTip="Replay" Source="Resources/Images/UI/Replay.png" MouseEnter="btnVideoControl_MouseEnter" MouseLeave="btnVideoControl_MouseLeave" MouseUp="btnReplay_MouseUp" />
</StackPanel>
<StackPanel x:Name="stpMiscControls" Orientation="Horizontal" HorizontalAlignment="Right" Grid.Column="1">
<Image x:Name="btnFullScreen" Height="25" Margin="5" ToolTip="Fullscreen" Source="Resources/Images/UI/FullScreen.png" MouseEnter="btnVideoControl_MouseEnter" MouseLeave="btnVideoControl_MouseLeave" MouseUp="btnFullScreen_MouseUp" />
<Image x:Name="btnSettings" Height="30" Margin="5,5,10,5" ToolTip="Settings" Source="Resources/Images/UI/Settings.png" MouseEnter="btnVideoControl_MouseEnter" MouseLeave="btnVideoControl_MouseLeave" />
</StackPanel>
</Grid>
</Grid>
</Grid>
The rule when using Trigger (in case TargetName can't be used) is the Trigger should belong to the element which has the properties you want to modify. In this case the Trigger should belong to the grdControls. However you can use DataTrigger to walk up the tree and listen to some other property change of any visual upwards in the tree. The following code should work:
<Style x:Key="FadeInOut" TargetType="Grid">
<Style.Triggers>
<DataTrigger Binding="{Binding IsMouseOver, ElementName=grdMain}"
Value="true">
<DataTrigger.EnterActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:1" To="40"
Storyboard.TargetProperty="Height"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.EnterActions>
<DataTrigger.ExitActions>
<BeginStoryboard>
<Storyboard>
<DoubleAnimation Duration="0:0:1" To="0"
Storyboard.TargetProperty="Height"/>
</Storyboard>
</BeginStoryboard>
</DataTrigger.ExitActions>
</DataTrigger>
</Style.Triggers>
</Style>
The second approach close to what Peter Dunno suggested in his comment requires you to have to set the EventTrigger directly in the Triggers property of the main Grid. You can either set the Storyboards directly or define them as Resource. Here is the code for that approach:
<Grid x:Name="grdMain" Background="Black">
<Grid.Triggers>
<EventTrigger RoutedEvent="Control.MouseEnter">
<BeginStoryboard>
<Storyboard TargetName="grdControls">
<DoubleAnimation Duration="0:0:1" To="40"
Storyboard.TargetProperty="Height"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
<EventTrigger RoutedEvent="Control.MouseLeave">
<BeginStoryboard>
<Storyboard TargetName="grdControls">
<DoubleAnimation Duration="0:0:1" To="0"
Storyboard.TargetProperty="Height"/>
</Storyboard>
</BeginStoryboard>
</EventTrigger>
</Grid.Triggers>
<!-- remaining code -->
</Grid>
Note that the Style you define now is no longer needed.

Categories