public static Task <bool> AnimateRowHeightAsync(
            this Grid view,
            RowDefinition rowDefinition,
            double rowExpandedHeight,
            bool isVisible,
            string animationName,
            bool dontAnimate = false)
        {
            const double Tolerance = 2f;
            var          tcs       = new TaskCompletionSource <bool>();
            Animation    animation;

            if (view.AbortAnimation(animationName))
            {
            }

            if (isVisible)
            {
                if (dontAnimate)
                {
                    rowDefinition.Height = rowExpandedHeight;
                    tcs.SetResult(true);
                    return(tcs.Task);
                }

                if (rowDefinition.Height.Value > (rowExpandedHeight - Tolerance))
                {
                    tcs.SetResult(false);
                    return(tcs.Task);
                }

                // Move back to original height
                animation = new Animation(
                    d => rowDefinition.Height = new GridLength(Clamp(d, 0, double.MaxValue)),
                    rowDefinition.Height.Value,
                    rowExpandedHeight,
                    Easing.Linear,
                    () => animation = null);
            }
            else
            {
                if (dontAnimate)
                {
                    rowDefinition.Height = ZeroHeightGrid;
                    tcs.SetResult(true);
                    return(tcs.Task);
                }

                if (Math.Abs(rowDefinition.Height.Value) < Tolerance)
                {
                    tcs.SetResult(false);
                    return(tcs.Task);
                }

                // Hide the row
                animation = new Animation(
                    d => rowDefinition.Height = new GridLength(Clamp(d, 0, double.MaxValue)),
                    rowExpandedHeight,
                    0,
                    Easing.Linear,
                    () => animation = null);
            }

            try
            {
                view.Animate(
                    animationName,
                    animation,
                    length: 400,
                    finished: (value, success) => tcs.TrySetResult(success));
            }
            catch (Exception)
            {
                tcs.SetResult(false);
            }

            return(tcs.Task);
        }