Skip to content

Instantly share code, notes, and snippets.

@Vanlalhriata
Created May 22, 2015 14:04
Show Gist options
  • Save Vanlalhriata/6aeb954ff82f72c2b389 to your computer and use it in GitHub Desktop.
Save Vanlalhriata/6aeb954ff82f72c2b389 to your computer and use it in GitHub Desktop.
WPF Animated WrapPanel
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Animation;
namespace ExpandDemo
{
class AnimatedWrapPanel : Panel
{
protected override Size MeasureOverride(Size availableSize)
{
Size infiniteSize = new Size(double.PositiveInfinity, double.PositiveInfinity);
double curX = 0, curY = 0; // The top left (x,y) coordiantes of each child
double curLineHeight = 0; // The current height of the Panel
foreach (UIElement child in Children)
{
// Give the child maximum space to expand to. This will set its DesiredSize
child.Measure(infiniteSize);
// Wrap child to next line if it doesn't fit
if (curX + child.DesiredSize.Width > availableSize.Width)
{
curY += curLineHeight;
curX = 0;
curLineHeight = 0;
}
// Next child will be placed next to this child
curX += child.DesiredSize.Width;
// Record the maximum Height the current row will require
if (child.DesiredSize.Height > curLineHeight)
curLineHeight = child.DesiredSize.Height;
}
// The final height the Panel will require
curY += curLineHeight;
Size resultSize = new Size();
// Should not return infinity as DesiredSize of the Panel
resultSize.Width = double.IsPositiveInfinity(availableSize.Width) ? curX : availableSize.Width;
resultSize.Height = double.IsPositiveInfinity(availableSize.Height) ? curY : availableSize.Height;
return resultSize;
}
protected override Size ArrangeOverride(Size finalSize)
{
if (this.Children == null || this.Children.Count == 0)
return finalSize;
TranslateTransform trans = null;
double curX = 0, curY = 0, curLineHeight = 0;
foreach (UIElement child in Children)
{
trans = child.RenderTransform as TranslateTransform;
if (trans == null)
{
child.RenderTransformOrigin = new Point(0, 0);
trans = new TranslateTransform();
child.RenderTransform = trans;
}
if (curX + child.DesiredSize.Width > finalSize.Width)
{ //Wrap to next line
curY += curLineHeight;
curX = 0;
curLineHeight = 0;
}
child.Arrange(new Rect(0, 0, child.DesiredSize.Width,
child.DesiredSize.Height));
DoubleAnimation animation = new DoubleAnimation(0, TimeSpan.FromMilliseconds(1000));
animation.EasingFunction = new CubicEase() { EasingMode = EasingMode.EaseOut };
animation.To = curX;
trans.BeginAnimation(TranslateTransform.XProperty, animation, HandoffBehavior.Compose);
animation.To = curY;
trans.BeginAnimation(TranslateTransform.YProperty, animation, HandoffBehavior.Compose);
curX += child.DesiredSize.Width;
if (child.DesiredSize.Height > curLineHeight)
curLineHeight = child.DesiredSize.Height;
}
return finalSize;
}
}
}
@Yusefdev
Copy link

using this code cause memory problem.its not a problem but will use more and more memory over time.

@Yusefdev
Copy link

any idea how to fix it?

@Vanlalhriata
Copy link
Author

using this code cause memory problem.its not a problem but will use more and more memory over time.

@Yusefdev Good catch! There's probably a memory leak from the DoubleAnimation instance. I can't try it out myself right now but I'd suggest removing the animation or something similar on its Completed event.

If you do fix it in the meantime, feel free to fork the gist and link to it here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment