/// <summary>
        /// Create a layout test that adds a series of elements to a panel and
        /// then verifies their positions once they have all been added.  An
        /// element will be created and added for each function used to compute
        /// a position.
        /// </summary>
        /// <param name="root">Root object containing the panel to test.</param>
        /// <param name="panel">Panel to test.</param>
        /// <param name="computePositions">
        /// Functions to compute the final positions of the elements that are
        /// added to the panel.  The functions can also customize the element
        /// (by setting size, etc.) before returning the desired final position.
        /// </param>
        public void TestLayoutAsync(UIElement root, Panel panel, params Func <ContentControl, Rect>[] computePositions)
        {
            Assert.IsNotNull(root);
            Assert.IsNotNull(panel);
            computePositions = computePositions ?? new Func <ContentControl, Rect>[] { };

            // Add a handler to determine when the panel is loaded (note: we
            // check the panel instead of the root as it's deeper in the tree)
            bool isLoaded = false;

            panel.Loaded += delegate { isLoaded = true; };

            // Add the root to the test surface and wait until its child Panel
            // is loaded before testing
            EnqueueCallback(() => TestPanel.Children.Add(root));
            EnqueueConditional(() => isLoaded);

            // Add the elements to the Panel
            List <Rect> positions = new List <Rect>();
            int         count     = 0;

            foreach (Func <ContentControl, Rect> computePosition in computePositions)
            {
                LayoutTestContentControl control = new LayoutTestContentControl {
                    Content = count++
                };
                panel.Children.Add(control);
                positions.Add(computePosition(control));
            }
            Assert.AreEqual(computePositions.Length, positions.Count);

            // Allow the visual tree to refresh before verifying positions
            EnqueueVisualDelay(DefaultVisualDelayInMilliseconds);

            // Verify the final positions of the elements
            EnqueueCallback(() =>
            {
                for (int i = 0; i < positions.Count; i++)
                {
                    LayoutTestContentControl element = panel.Children[i] as LayoutTestContentControl;
                    Rect desired = positions[i];
                    Point offset = element.TransformToVisual(panel).Transform(new Point(0, 0));
                    Rect actual  = new Rect(offset.X, offset.Y, element.ActualWidth, element.ActualHeight);
                    Assert.AreEqual(desired, actual, "Element {0} expected to be arranged at <{1}> instead of <{2}>.", i, desired, actual);
                }
            });

            // Remove the panel from the test surface and finish the test
            EnqueueCallback(() => TestPanel.Children.Remove(root));
            EnqueueTestComplete();
        }
        /// <summary>
        /// Create a layout test that adds a series of elements to a panel and
        /// then verifies their positions once they have all been added.  An
        /// element will be created and added for each function used to compute
        /// a position.
        /// </summary>
        /// <param name="root">Root object containing the panel to test.</param>
        /// <param name="panel">Panel to test.</param>
        /// <param name="computePositions">
        /// Functions to compute the final positions of the elements that are
        /// added to the panel.  The functions can also customize the element
        /// (by setting size, etc.) before returning the desired final position.
        /// </param>
        public void TestLayoutAsync(UIElement root, Panel panel, params Func<ContentControl, Rect>[] computePositions)
        {
            Assert.IsNotNull(root);
            Assert.IsNotNull(panel);
            computePositions = computePositions ?? new Func<ContentControl, Rect>[] { };

            // Add a handler to determine when the panel is loaded (note: we
            // check the panel instead of the root as it's deeper in the tree)
            bool isLoaded = false;
            panel.Loaded += delegate { isLoaded = true; };

            // Add the root to the test surface and wait until its child Panel
            // is loaded before testing
            EnqueueCallback(() => TestPanel.Children.Add(root));
            EnqueueConditional(() => isLoaded);

            // Add the elements to the Panel
            List<Rect> positions = new List<Rect>();
            int count = 0;
            foreach (Func<ContentControl, Rect> computePosition in computePositions)
            {
                LayoutTestContentControl control = new LayoutTestContentControl { Content = count++ };
                panel.Children.Add(control);
                positions.Add(computePosition(control));
            }
            Assert.AreEqual(computePositions.Length, positions.Count);

            // Allow the visual tree to refresh before verifying positions
            EnqueueVisualDelay(DefaultVisualDelayInMilliseconds);

            // Verify the final positions of the elements
            EnqueueCallback(() =>
                {
                    for (int i = 0; i < positions.Count; i++)
                    {
                        LayoutTestContentControl element = panel.Children[i] as LayoutTestContentControl;
                        Rect desired = positions[i];
                        Point offset = element.TransformToVisual(panel).Transform(new Point(0, 0));
                        Rect actual = new Rect(offset.X, offset.Y, element.ActualWidth, element.ActualHeight);
                        Assert.AreEqual(desired, actual, "Element {0} expected to be arranged at <{1}> instead of <{2}>.", i, desired, actual);
                    }
                });

            // Remove the panel from the test surface and finish the test
            EnqueueCallback(() => TestPanel.Children.Remove(root));
            EnqueueTestComplete();
        }