Search code examples
c#.netwpfxamlparallel-processing

Running multiple animations in parallel and at the same time


I am aware that this issue has already been raised, but the solutions offered (such as this) are insufficient for me.

I'd like to minimize my app window as shown below: Like this

These are my codes (unnecessary codes have not been posted):

XAML:

<Window x:Name="GanjAsemanMainWindow" x:Class="Ganj_Aseman.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:Ganj_Aseman"
    mc:Ignorable="d"
    Loaded="GanjAsemanMainWindow_Loaded" AllowsTransparency="True" Background="Transparent" FontSize="13" Height="535" ResizeMode="CanResizeWithGrip" Title="MainWindow" Width="764" WindowStyle="None">
<Window.RenderTransform>
    <RotateTransform CenterX="{Binding}" CenterY="{Binding}" Angle="{Binding}"/>
</Window.RenderTransform>
<Window.Resources>
    <Storyboard x:Key="WindowRotation">
        <DoubleAnimation BeginTime="00:00:00" SpeedRatio="0.9" Duration="00:00:2" Storyboard.TargetName="GanjAsemanMainWindow" From="0" To="360" AutoReverse="False" Storyboard.TargetProperty="(UIElement.RenderTransform).(RotateTransform.Angle)"/>
    </Storyboard>
</Window.Resources>
<Grid>
    <Image x:Name="MinimizeIconImage" PreviewMouseLeftButtonDown="MinimizeIconImage_PreviewMouseLeftButtonDown" MouseEnter="MinimizeIconImage_MouseEnter" MouseLeave="MinimizeIconImage_MouseLeave" GotFocus="MinimizeIconImage_GotFocus" LostFocus="MinimizeIconImage_LostFocus" Focusable="True" FocusVisualStyle="{x:Null}" Cursor="Hand" Height="47"  VerticalAlignment="Top" Source="{Binding}" Margin="0,2,67,0" HorizontalAlignment="Right" Width="52">
        <Image.Triggers>
            <EventTrigger RoutedEvent="PreviewMouseLeftButtonDown">
                <BeginStoryboard>
                    <Storyboard>
                        <ParallelTimeline BeginTime="00:00:00" SpeedRatio="0.9" Storyboard.TargetName="GanjAsemanMainWindow">
                            <DoubleAnimation Duration="00:00:2" From="{Binding Path=ActualHeight,ElementName=GanjAsemanMainWindow}" To="0" AutoReverse="False" Storyboard.TargetProperty="Height"/>
                            <DoubleAnimation Duration="00:00:2" From="{Binding Path=ActualWidth,ElementName=GanjAsemanMainWindow}" To="0" AutoReverse="False" Storyboard.TargetProperty="Width"/>
                            <DoubleAnimation Duration="00:00:2.5" From="100" To="0" AutoReverse="False" Storyboard.TargetProperty="Opacity"/>
                        </ParallelTimeline>
                    </Storyboard>
                </BeginStoryboard>
            </EventTrigger>
        </Image.Triggers>
    </Image>
</Grid>

C#:

private void MinimizeIconImage_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
    RotateTransform RT = new RotateTransform(0, ActualWidth / 2, ActualHeight / 2);
    GanjAsemanMainWindow.RenderTransform = RT;
    (Resources["WindowRotation"] as Storyboard).Begin();
}

But, DoubleAnimations are performed sequentially rather than in parallel, and as a result, the following output is obtained: Output

I think it will work fine if we can bind three properties to a Storyboard.TargetProperty.

I use the following tools:

  • .NET Framework 4.5
  • WPF

Thank you for your time.

Best regards,

Reza Jaferi


Solution

  • Instead of animating the Width and Height of the Window, you may as well animate a ScaleTransform, similar to the RotateTransform that you already have. There is also no need for a ParallelTimeline.

    You must however set the Window's RenderTransformOrigin property.

    Here is a minimal example:

    <Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            x:Class="WindowAnimationTest.MainWindow"
            Background="AliceBlue" Height="535" Width="764"
            AllowsTransparency="True" WindowStyle="None"
            RenderTransformOrigin="0.5,0.5">
        <Window.RenderTransform>
            <TransformGroup>
                <RotateTransform/>
                <ScaleTransform/>
            </TransformGroup>
        </Window.RenderTransform>
        <Window.Resources>
            <Storyboard x:Key="MinimizeAnimations">
                <DoubleAnimation
                    Storyboard.TargetProperty="RenderTransform.Children[0].Angle"
                    Duration="0:0:2" To="360"/>
                <DoubleAnimation
                    Storyboard.TargetProperty="RenderTransform.Children[1].ScaleX"
                    Duration="0:0:2" To="0"/>
                <DoubleAnimation
                    Storyboard.TargetProperty="RenderTransform.Children[1].ScaleY"
                    Duration="0:0:2" To="0"/>
                <DoubleAnimation
                    Storyboard.TargetProperty="Opacity"
                    Duration="0:0:2.5" To="0"/>
            </Storyboard>
        </Window.Resources>
        <Window.Triggers>
            <EventTrigger RoutedEvent="MouseLeftButtonDown">
                <BeginStoryboard Storyboard="{StaticResource MinimizeAnimations}"/>
            </EventTrigger>
        </Window.Triggers>
        <Grid>
            <TextBlock Text="Like this" FontSize="40"
                       HorizontalAlignment="Center" VerticalAlignment="Center"/>
        </Grid>
    </Window>