private static Storyboard CreateLayoutTransitionStoryboard()

in src/Microsoft.Xaml.Behaviors/Core/ExtendedVisualStateManager.cs [1347:1453]


        private static Storyboard CreateLayoutTransitionStoryboard(VisualTransition transition, List<FrameworkElement> movingElements, Dictionary<FrameworkElement, double> oldOpacities)
        {
            Duration duration = transition != null ? transition.GeneratedDuration : new Duration(TimeSpan.Zero);
            IEasingFunction ease = transition != null ? transition.GeneratedEasingFunction : null;

            Storyboard layoutTransitionStoryboard = new Storyboard();
            layoutTransitionStoryboard.Duration = duration;

            // Handle the positions of elements that are on the move
            foreach (FrameworkElement movingElement in movingElements)
            {
                WrapperCanvas parentCanvas = movingElement.Parent as WrapperCanvas;

                if (parentCanvas == null)
                {
                    continue;
                }

                {
                    DoubleAnimation animation = new DoubleAnimation() { From = 1, To = 0, Duration = duration };
                    animation.EasingFunction = ease;
                    Storyboard.SetTarget(animation, parentCanvas);
                    Storyboard.SetTargetProperty(animation, new PropertyPath(WrapperCanvas.SimulationProgressProperty));
                    layoutTransitionStoryboard.Children.Add(animation);

                    // prime the pump
                    parentCanvas.SimulationProgress = 1;
                }

                Rect newRect = parentCanvas.NewRect;

                // Do-nothing animation to override the width/height of the Canvas without stomping the values, so that the Canvas unwrap will replace the right ones
                // Needed in some cases because the width/height may be Auto and the Canvas would shrink to zero size
                if (!IsClose(parentCanvas.Width, newRect.Width))
                {
                    DoubleAnimation animation = new DoubleAnimation() { From = newRect.Width, To = newRect.Width, Duration = duration };
                    Storyboard.SetTarget(animation, parentCanvas);
                    Storyboard.SetTargetProperty(animation, new PropertyPath(FrameworkElement.WidthProperty));
                    layoutTransitionStoryboard.Children.Add(animation);
                }

                if (!IsClose(parentCanvas.Height, newRect.Height))
                {
                    DoubleAnimation animation = new DoubleAnimation() { From = newRect.Height, To = newRect.Height, Duration = duration };
                    Storyboard.SetTarget(animation, parentCanvas);
                    Storyboard.SetTargetProperty(animation, new PropertyPath(FrameworkElement.HeightProperty));
                    layoutTransitionStoryboard.Children.Add(animation);
                }

                if (parentCanvas.DestinationVisibilityCache == Visibility.Collapsed)
                {
                    Thickness margin = parentCanvas.Margin;

                    if (!IsClose(margin.Left, 0) || !IsClose(margin.Top, 0) || !IsClose(margin.Right, 0) || !IsClose(margin.Bottom, 0))
                    {
                        ObjectAnimationUsingKeyFrames animation = new ObjectAnimationUsingKeyFrames() { Duration = duration };
                        DiscreteObjectKeyFrame keyFrame = new DiscreteObjectKeyFrame() { KeyTime = TimeSpan.Zero, Value = new Thickness() };
                        animation.KeyFrames.Add(keyFrame);
                        Storyboard.SetTarget(animation, parentCanvas);
                        Storyboard.SetTargetProperty(animation, new PropertyPath(FrameworkElement.MarginProperty));
                        layoutTransitionStoryboard.Children.Add(animation);
                    }

                    if (!IsClose(parentCanvas.MinWidth, 0))
                    {
                        DoubleAnimation animation = new DoubleAnimation() { From = 0, To = 0, Duration = duration };
                        Storyboard.SetTarget(animation, parentCanvas);
                        Storyboard.SetTargetProperty(animation, new PropertyPath(FrameworkElement.MinWidthProperty));
                        layoutTransitionStoryboard.Children.Add(animation);
                    }

                    if (!IsClose(parentCanvas.MinHeight, 0))
                    {
                        DoubleAnimation animation = new DoubleAnimation() { From = 0, To = 0, Duration = duration };
                        Storyboard.SetTarget(animation, parentCanvas);
                        Storyboard.SetTargetProperty(animation, new PropertyPath(FrameworkElement.MinHeightProperty));
                        layoutTransitionStoryboard.Children.Add(animation);
                    }
                }
            }

            // Handle the opacity/visibility of elements that are changing visibility
            foreach (FrameworkElement visibilityElement in oldOpacities.Keys)
            {
                WrapperCanvas parentCanvas = visibilityElement.Parent as WrapperCanvas;

                if (parentCanvas == null)
                {
                    continue;
                }

                double oldOpacity = oldOpacities[visibilityElement];
                double newOpacity = (parentCanvas.DestinationVisibilityCache == Visibility.Visible ? 1.0 : 0.0);

                // Animate the opacity to smooth out the visibility change
                if (!IsClose(oldOpacity, 1) || !IsClose(newOpacity, 1))
                {
                    DoubleAnimation animation = new DoubleAnimation() { From = oldOpacity, To = newOpacity, Duration = duration };
                    animation.EasingFunction = ease;
                    Storyboard.SetTarget(animation, parentCanvas);
                    Storyboard.SetTargetProperty(animation, new PropertyPath(FrameworkElement.OpacityProperty));
                    layoutTransitionStoryboard.Children.Add(animation);
                }
            }

            return layoutTransitionStoryboard;
        }