How to animate Margin property in WPF

31,148

Solution 1

Margin property can be animated using ThicknessAnimation

<Storyboard >
     <ThicknessAnimationUsingKeyFrames Storyboard.TargetProperty="Margin" BeginTime="00:00:00">
        <SplineThicknessKeyFrame KeyTime="00:00:00" Value="134, 70,0,0" />
        <SplineThicknessKeyFrame KeyTime="00:00:03" Value="50, 70,0,0" />
     </ThicknessAnimationUsingKeyFrames>
</Storyboard>

Solution 2

Actually, ya you can do what you want to do, exactly as you want to do using RenderTransform mixed with some DoubleAnimation and even add some extra flair to it, for example;

<Grid x:Name="TheObject" Opacity="0">
    <Grid.RenderTransform>
        <TranslateTransform x:Name="MoveMeBaby" X="50" />
    </Grid.RenderTransform>
    <Grid.Triggers>
        <EventTrigger RoutedEvent="Grid.Loaded">
            <BeginStoryboard>
                <Storyboard>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="MoveMeBaby" 
                                                   Storyboard.TargetProperty="X">
                        <SplineDoubleKeyFrame KeyTime="0:0:1.25" Value="0" />
                    </DoubleAnimationUsingKeyFrames>
                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="TheObject"
                                                   Storyboard.TargetProperty="Opacity">
                        <SplineDoubleKeyFrame KeyTime="0:0:1.55" Value="1" />
                    </DoubleAnimationUsingKeyFrames>
                </Storyboard>
            </BeginStoryboard>
        </EventTrigger>
    </Grid.Triggers>
</Grid>

Will move that object 50px on the X axis and even fade it in while it does so. Give it a shot and play with the values of the X property and the KeyTime to get what you want. Hope this helps, cheers.

Solution 3

You can't animate Margin.Left (because Left is not a dependency property), but you can animate Margin. Use ObjectAnimationUsingKeyFrames:

<Storyboard x:Key="MoveMe">
    <ObjectAnimationUsingKeyFrames BeginTime="00:00:00" 
            Storyboard.TargetName="GroupTileSecond" 
            Storyboard.TargetProperty="Margin">
        <DiscreteObjectKeyFrame KeyTime="00:00:00">
            <DiscreteObjectKeyFrame.Value>
                <Thickness>134,70,0,0</Thickness>
            </DiscreteObjectKeyFrame.Value>
        </DiscreteObjectKeyFrame>
        <DiscreteObjectKeyFrame KeyTime="00:00:03">
            <DiscreteObjectKeyFrame.Value>
                <Thickness>50,70,0,0</Thickness>
            </DiscreteObjectKeyFrame.Value>
        </DiscreteObjectKeyFrame>
    </ObjectAnimationUsingKeyFrames>
</Storyboard>

There are some alternatives that allow you to use a DoubleAnimation, rather than key frames:

  1. Place your target inside a Canvas, and animate its x position using Canvas.Left.
  2. Apply a TranslateTransform to your target, and animate its x position using TranslateTransform.X.

Solution 4

As an alternative answer @McGarnagle you can use animation for HorizontalAlignment and VerticalAlignment properties.

Example:

<ObjectAnimationUsingKeyFrames Storyboard.TargetName="GroupTileSecond" 
                               Storyboard.TargetProperty="HorizontalAlignment">

    <DiscreteObjectKeyFrame KeyTime="0:0:0">
        <DiscreteObjectKeyFrame.Value>
            <HorizontalAlignment>Center</HorizontalAlignment>
        </DiscreteObjectKeyFrame.Value>
    </DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>

Solution 5

i just created a animation. code bellow

using System;
using System.Windows;
using System.Windows.Media.Animation;

namespace ImagesSwitcher
{
    class MarginAnimation : AnimationTimeline
    {
        protected override Freezable CreateInstanceCore()
        {
            return new MarginAnimation();
        }

    public override Type TargetPropertyType => typeof(Thickness);

    private double GetContrast(double dTo,double dFrom,double process)
    {
        if (dTo < dFrom)
        {
            return dTo + (1 - process) * (dFrom - dTo);
        }

        return dFrom + (dTo - dFrom) * process;
    }

    public override object GetCurrentValue(object defaultOriginValue, object defaultDestinationValue, AnimationClock animationClock)
    {
        if (!From.HasValue || !To.HasValue || animationClock.CurrentProgress == null) return null;
        var progress = animationClock.CurrentProgress.Value;

        if (progress.Equals(0)) return null;

        if (progress.Equals(1)) return To.Value; 

        var fromValue = From.Value;
        var toValue = To.Value;

        var l = GetContrast(toValue.Left ,fromValue.Left, progress);
        var t = GetContrast(toValue.Top, fromValue.Top, progress);
        var r = GetContrast(toValue.Right, fromValue.Right, progress);
        var b = GetContrast(toValue.Bottom, fromValue.Bottom, progress);

        return new Thickness(l,t,r,b);
    }

    public Thickness? To
    {
        set => SetValue(ToProperty, value);
        get => (Thickness)GetValue(ToProperty);
    }
    public static DependencyProperty ToProperty = DependencyProperty.Register("To", typeof(Thickness), typeof(MarginAnimation), new PropertyMetadata(null));

    public Thickness? From
    {
        set => SetValue(FromProperty, value);
        get => (Thickness)GetValue(FromProperty);
    }
    public static DependencyProperty FromProperty = DependencyProperty.Register("From", typeof(Thickness), typeof(MarginAnimation), new PropertyMetadata(null));

}

}

Share:
31,148
Gaja Kannan
Author by

Gaja Kannan

Updated on August 08, 2022

Comments

  • Gaja Kannan
    Gaja Kannan almost 2 years

    I want to move animate an rectangle object to move it in x-axis. I am new to WPF animation, started out with the following:

    <Storyboard x:Key="MoveMe">
        <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" 
                                       Storyboard.TargetName="GroupTileSecond"
                                       Storyboard.TargetProperty="(**Margin.Left**)">
    
            <SplineDoubleKeyFrame KeyTime="00:00:00" Value="**134, 70,0,0**" />
            <SplineDoubleKeyFrame KeyTime="00:00:03" Value="**50, 70,0,0**" />
        </DoubleAnimationUsingKeyFrames>
    </Storyboard>
    

    Obviously found out that I cant use Margin.Left as Storyboard.TargetProperty or use 134,70,0,0 in Value property.

    So, how do I move an object in XAML WPF.

  • Chris W.
    Chris W. over 10 years
    @McGarnagle & AnatoliyNikolaev - +1 to both you guys too, got to love when 3 guys can figure out different ways to screw in a light bulb :)
  • Chris W.
    Chris W. over 10 years
    Hah! another +1, forgot about the Thickness too
  • Chris W.
    Chris W. over 10 years
    Still, I just dig the fact you put a problem in front of some guys and each one has a different clever way. That alone is awesome, great show for the OP's first post, I love fun one's like these. Cheers!
  • Gaja Kannan
    Gaja Kannan over 10 years
    I got following error Exception "{"Cannot animate the 'Margin' property on a 'System.Windows.Shapes.Rectangle' using a 'System.Windows.Media.Animation.ObjectAnimationUsingKeyFrame‌​s'. For details see the inner exception."}" InnerException "{"The animation(s) applied to the 'Margin' property calculate a current value of '134,70,0,0', which is not a valid value for the property."}"
  • Gaja Kannan
    Gaja Kannan over 10 years
    Worked like a charm. Thanks!
  • McGarnagle
    McGarnagle over 10 years
    @GajaKannan hm ... try specifying the Thickness explicitly, as in my edit above.