Animate Image Left To Right

The basics of any animation is moving something from one location to the other. In this code snippet I use to Image elements to slide away previously selected image and slide in the newly selected one.

The Image elements need to sit in a Canvas in order to let the Left property make sence.
<Label x:Name="txtFile"  HorizontalAlignment="Stretch"  />
<Canvas HorizontalAlignment=
"Stretch" VerticalAlignment="Stretch">

<Image x:Name=
"newImage" Canvas.Left="0" Canvas.Top="0" />
<Image x:Name=
"oldImage" Canvas.Left="0" Canvas.Top="0" />

</Canvas>

assuming that I have already given the previously selected image, my new image file will be given through a function call like

AnimateLeftToRight(selectedFile);

This method will swap the images and create a storyboard to begin animating. I start the newImage from x-position that equals to minus Window.Width and the old one starts from 0 and moves to Window.Width:

/// <summary>
/// Begins a story which animates two images from left to right
/// the old image takes the source from te new image just before assigning the new one
/// and they move together in the distance of Window.Width
/// </summary>
/// <param name="path">the path of the new image</param>
private void AnimateLeftToRight(string path)
{
oldImage.Source = newImage.Source;
newImage.Source =
new BitmapImage(new Uri(path));

var myStoryboard =
new Storyboard();

myStoryboard.Children.Add(MakeAnimation(-
this.Width, 0, "newImage"));
myStoryboard.Children.Add(MakeAnimation(
0, this.Width, "oldImage"));

myStoryboard.Begin(
this);
}

Making animation can be done in different ways using different EasingFunction, But this one looked easy to understand and look nice on my example:

/// <summary>
/// Creates a DoubleAnimation that moves the target from left to right
/// </summary>
/// <param name="from">starting point X</param>
/// <param name="to">ending point X</param>
/// <param name="target">the target element to set the x to </param>
/// <returns>the created animation</returns>
private DoubleAnimation MakeAnimation(double from, double to, string target)
{
const double durationSeconds = 1;

var animation =
new DoubleAnimation
{
Duration =
new Duration(TimeSpan.FromSeconds(durationSeconds)),
AutoReverse =
false,
From = from,
To = to,
EasingFunction =
new PowerEase()
{
EasingMode = EasingMode.EaseInOut,
Power =
5
}
};

Storyboard.SetTargetName(animation, target);
Storyboard.SetTargetProperty(animation,
new PropertyPath(Canvas.LeftProperty));

return animation;
}

Geometry and Mini-Language

StreamGeometry is a light-weight alternative to the PathGeometry class for
creating complex geometric shapes. You can use StreamGeometry when you
need to describe a complex geometry but don’t want the overhead of supporting
data binding, animation, and modification.
There are two classes in WPF that provide the mini-language for describing
geometric paths: StreamGeometry, and PathFigureCollection. You need to use
the StreamGeometry mini-language when you set a property of the Geometry
type, such as the Data property of a Path element.

<path stroke="Blue" data="M 100 120 L 200 120 L 200 220 L 100 170">
</path>

This path uses a sequence of four commands. The first command, M, creates the
PathFigure and sets the starting point to (100, 120). The following three
commands (L) create line segments.

See also Mini-Language in MSDN

From the book of Practical WPF Graphics Programming

L endPoint : The end point of the line.
H x : The x-coordinate of the end point of the line.
V y : The y-coordinate of the end point of the line.

F0 specifies the EvenOdd fill rule.
F1 specifies the Nonzero fill rule.
An uppercase M indicates that startPoint is an absolute value; a lowercase m indicates that startPoint is an offset to the previous point

C controlPoint1 controlPoint2 endPoint : Cubic Bezier Curve Command
A size rotationAngle isLargeArcFlag sweepDirectionFlag endPoint : Creates an elliptical arc between the current point and the specified end point.

Z : Ends the current figure and creates a line that connects the current point to the starting point of the figure.

Introducing Custom DependencyProperty in WPF

In this sample code I want to introduce three DependencyProperty called Overlap Rotation and UpperOffset in a custom control OverlapStackPannel. The control is simply a StackPanel that arranges the containing items in a custom manner.

In the ArrageOverride method I will use these three properties to locate each item as follows:

   protected  override  System.Windows.Size  ArrangeOverride(System.Windows.Size  arrangeSize)
   {
     UIElementCollection  children = this.InternalChildren;

    int  childrenResolved = 0;
    foreach  (UIElement  child in  children)
    {
 Rect  targetRect = new  Rect ();
 targetRect.X = this .Overlap * childrenResolved;
 targetRect.Y = this .UpperOffset;
 targetRect.Width = child.DesiredSize.Width;
 targetRect.Height = child.DesiredSize.Height;
 child.Arrange(targetRect);
 child.RenderTransform = new  RotateTransform (this .Rotation);
 childrenResolved++;
    }
    return  arrangeSize;
   }


To Achieve this I need to set the properties as follows:

  #region  Property: UpperOffset
  public  static  readonly  DependencyProperty  UpperOffsetProperty = DependencyProperty .Register("UpperOffset" , typeof (double ), typeof (OverlapStackPanel ), new  FrameworkPropertyMetadata (double .NaN, FrameworkPropertyMetadataOptions .AffectsArrange));
      
  /// <summary> 
  /// set or get the upper offset for each item in the pannel 
  /// </summary> 
  public  double  UpperOffset
  {
    get 
    {
      return  (double )this .GetValue(OverlapStackPanel .UpperOffsetProperty);
    }
    set 
    {
      this .SetValue(OverlapStackPanel .UpperOffsetProperty, value );
    }
  }
  #endregion 

and similar for other two.
This makes my OverlapStackPanel having the properties in Blend like this:

Benefits

According to this nice article there are three main advantages of using DependencyProperties comparing to CLR properties:

  • Reduced memory footprint
  • Value inheritance
  • Change notification