private void AnchoringAtAlmostNearEdge(Orientation orientation)
        {
            using (ScrollPresenterTestHooksHelper scrollPresenterTestHooksHelper = new ScrollPresenterTestHooksHelper(
                       enableAnchorNotifications: true,
                       enableInteractionSourcesNotifications: true,
                       enableExpressionAnimationStatusNotifications: false))
            {
                ScrollPresenter scrollPresenter                 = null;
                AutoResetEvent  scrollPresenterLoadedEvent      = new AutoResetEvent(false);
                AutoResetEvent  scrollPresenterViewChangedEvent = new AutoResetEvent(false);

                RunOnUIThread.Execute(() =>
                {
                    scrollPresenter = new ScrollPresenter();

                    SetupDefaultAnchoringUI(orientation, scrollPresenter, scrollPresenterLoadedEvent);
                });

                WaitForEvent("Waiting for Loaded event", scrollPresenterLoadedEvent);

                double horizontalOffset = orientation == Orientation.Vertical ? 0.0 : 1.0;
                double verticalOffset   = orientation == Orientation.Vertical ? 1.0 : 0.0;

                ScrollTo(scrollPresenter, horizontalOffset, verticalOffset, ScrollingAnimationMode.Disabled, ScrollingSnapPointsMode.Ignore);

                RunOnUIThread.Execute(() =>
                {
                    scrollPresenter.ViewChanged += delegate(ScrollPresenter sender, object args)
                    {
                        Log.Comment("ViewChanged - HorizontalOffset={0}, VerticalOffset={1}, ZoomFactor={2}",
                                    sender.HorizontalOffset, sender.VerticalOffset, sender.ZoomFactor);
                        Log.Comment("ViewChanged - CurrentAnchor is " + (sender.CurrentAnchor == null ? "null" : "non-null"));
                        scrollPresenterViewChangedEvent.Set();
                    };

                    Log.Comment("Inserting child at near edge");
                    InsertStackPanelChild((scrollPresenter.Content as Border).Child as StackPanel, 1 /*operationCount*/, 0 /*newIndex*/, 1 /*newCount*/);
                });

                WaitForEvent("Waiting for ScrollPresenter.ViewChanged event", scrollPresenterViewChangedEvent);
                IdleSynchronizer.Wait();

                RunOnUIThread.Execute(() =>
                {
                    Log.Comment("ScrollPresenter offset change expected");
                    if (orientation == Orientation.Vertical)
                    {
                        Verify.AreEqual(127.0, scrollPresenter.VerticalOffset);
                    }
                    else
                    {
                        Verify.AreEqual(127.0, scrollPresenter.HorizontalOffset);
                    }

                    Log.Comment("ScrollPresenter CurrentAnchor is " + (scrollPresenter.CurrentAnchor == null ? "null" : "non-null"));
                    Verify.IsNotNull(scrollPresenter.CurrentAnchor);
                });
            }
        }
        private void AnchoringAtNearEdge(Orientation orientation)
        {
            using (ScrollPresenterTestHooksHelper scrollPresenterTestHooksHelper = new ScrollPresenterTestHooksHelper(
                       enableAnchorNotifications: true,
                       enableInteractionSourcesNotifications: true,
                       enableExpressionAnimationStatusNotifications: false))
            {
                ScrollPresenter scrollPresenter            = null;
                AutoResetEvent  scrollPresenterLoadedEvent = new AutoResetEvent(false);

                RunOnUIThread.Execute(() =>
                {
                    scrollPresenter = new ScrollPresenter();

                    SetupDefaultAnchoringUI(orientation, scrollPresenter, scrollPresenterLoadedEvent);
                });

                WaitForEvent("Waiting for Loaded event", scrollPresenterLoadedEvent);

                RunOnUIThread.Execute(() =>
                {
                    Log.Comment("Inserting child at near edge");
                    InsertStackPanelChild((scrollPresenter.Content as Border).Child as StackPanel, 1 /*operationCount*/, 0 /*newIndex*/, 1 /*newCount*/);
                });

                IdleSynchronizer.Wait();

                RunOnUIThread.Execute(() =>
                {
                    Log.Comment("No ScrollPresenter offset change expected");
                    if (orientation == Orientation.Vertical)
                    {
                        Verify.AreEqual(0, scrollPresenter.VerticalOffset);
                    }
                    else
                    {
                        Verify.AreEqual(0, scrollPresenter.HorizontalOffset);
                    }
                });
            }
        }
        public void AnchoringAtRepeaterMiddle()
        {
            using (ScrollPresenterTestHooksHelper scrollPresenterTestHooksHelper = new ScrollPresenterTestHooksHelper(
                       enableAnchorNotifications: true,
                       enableInteractionSourcesNotifications: true,
                       enableExpressionAnimationStatusNotifications: false))
            {
                using (PrivateLoggingHelper privateLoggingHelper = new PrivateLoggingHelper("ScrollPresenter"))
                {
                    ScrollPresenter scrollPresenter                 = null;
                    AutoResetEvent  scrollPresenterLoadedEvent      = new AutoResetEvent(false);
                    AutoResetEvent  scrollPresenterViewChangedEvent = new AutoResetEvent(false);

                    RunOnUIThread.Execute(() =>
                    {
                        scrollPresenter = new ScrollPresenter();

                        SetupRepeaterAnchoringUI(scrollPresenter, scrollPresenterLoadedEvent);

                        scrollPresenter.HorizontalAnchorRatio = double.NaN;
                        scrollPresenter.VerticalAnchorRatio   = 0.5;
                    });

                    WaitForEvent("Waiting for Loaded event", scrollPresenterLoadedEvent);

                    ZoomTo(scrollPresenter, 2.0f, 0.0f, 0.0f, ScrollingAnimationMode.Enabled, ScrollingSnapPointsMode.Ignore);
                    ScrollTo(scrollPresenter, 0.0, 250.0, ScrollingAnimationMode.Enabled, ScrollingSnapPointsMode.Ignore, false /*hookViewChanged*/);

                    ItemsRepeater  repeater   = null;
                    TestDataSource dataSource = null;

                    RunOnUIThread.Execute(() =>
                    {
                        repeater   = (scrollPresenter.Content as Border).Child as ItemsRepeater;
                        dataSource = repeater.ItemsSource as TestDataSource;

                        scrollPresenter.ViewChanged += delegate(ScrollPresenter sender, object args) {
                            scrollPresenterViewChangedEvent.Set();
                        };

                        Log.Comment("Inserting items at the beginning");
                        dataSource.Insert(0 /*index*/, 2 /*count*/);
                    });

                    WaitForEvent("Waiting for ScrollPresenter.ViewChanged event", scrollPresenterViewChangedEvent);

                    RunOnUIThread.Execute(() =>
                    {
                        Log.Comment("ScrollPresenter offset change expected");
                        Verify.AreEqual(520.0, scrollPresenter.VerticalOffset);
                    });

                    RunOnUIThread.Execute(() =>
                    {
                        scrollPresenterViewChangedEvent.Reset();

                        Log.Comment("Removing items from the beginning");
                        dataSource.Remove(0 /*index*/, 2 /*count*/);
                    });

                    WaitForEvent("Waiting for ScrollPresenter.ViewChanged event", scrollPresenterViewChangedEvent);

                    RunOnUIThread.Execute(() =>
                    {
                        Log.Comment("ScrollPresenter offset change expected");
                        Verify.AreEqual(250.0, scrollPresenter.VerticalOffset);

                        Log.Comment("ScrollPresenter CurrentAnchor is " + (scrollPresenter.CurrentAnchor == null ? "null" : "non-null"));
                        Verify.IsNotNull(scrollPresenter.CurrentAnchor);
                    });
                }
            }
        }
        private void AnchoringWithOffsetCoercion(bool reduceAnchorOffset)
        {
            using (ScrollPresenterTestHooksHelper scrollPresenterTestHooksHelper = new ScrollPresenterTestHooksHelper(
                       enableAnchorNotifications: true,
                       enableInteractionSourcesNotifications: true,
                       enableExpressionAnimationStatusNotifications: false))
            {
                ScrollPresenter scrollPresenter                     = null;
                Border          anchorElement                       = null;
                AutoResetEvent  scrollPresenterLoadedEvent          = new AutoResetEvent(false);
                AutoResetEvent  scrollPresenterViewChangedEvent     = new AutoResetEvent(false);
                AutoResetEvent  scrollPresenterAnchorRequestedEvent = new AutoResetEvent(false);

                // This test validates that the ScrollPresenter accounts for maximum vertical offset (based on viewport and content extent)
                // when calculating the vertical offset shift for anchoring. The vertical offset cannot exceed content extent - viewport.

                RunOnUIThread.Execute(() =>
                {
                    Log.Comment("Visual tree setup");
                    anchorElement = new Border
                    {
                        Width             = 100,
                        Height            = 100,
                        Background        = new SolidColorBrush(Colors.Red),
                        Margin            = new Thickness(0, 600, 0, 0),
                        VerticalAlignment = VerticalAlignment.Top
                    };

                    Grid grid = new Grid();
                    grid.Children.Add(anchorElement);
                    grid.Width      = 200;
                    grid.Height     = 1000;
                    grid.Background = new SolidColorBrush(Colors.Gray);

                    scrollPresenter = new ScrollPresenter
                    {
                        Content = grid,
                        Width   = 200,
                        Height  = 200
                    };

                    scrollPresenter.Loaded += (object sender, RoutedEventArgs e) =>
                    {
                        Log.Comment("ScrollPresenter.Loaded event handler");
                        scrollPresenterLoadedEvent.Set();
                    };

                    scrollPresenter.ViewChanged += delegate(ScrollPresenter sender, object args)
                    {
                        Log.Comment("ViewChanged - HorizontalOffset={0}, VerticalOffset={1}, ZoomFactor={2}",
                                    sender.HorizontalOffset, sender.VerticalOffset, sender.ZoomFactor);
                        Log.Comment("ViewChanged - CurrentAnchor is " + (sender.CurrentAnchor == null ? "null" : "non-null"));
                        if ((reduceAnchorOffset && sender.VerticalOffset == 400) ||
                            (!reduceAnchorOffset && sender.VerticalOffset == 500))
                        {
                            scrollPresenterViewChangedEvent.Set();
                        }
                    };

                    scrollPresenter.AnchorRequested += delegate(ScrollPresenter sender, ScrollingAnchorRequestedEventArgs args)
                    {
                        Log.Comment("AnchorRequested - Forcing the red Border to be the ScrollPresenter anchor.");
                        args.AnchorElement = anchorElement;
                        scrollPresenterAnchorRequestedEvent.Set();
                    };

                    Log.Comment("Setting window content");
                    Content = scrollPresenter;
                });

                WaitForEvent("Waiting for ScrollPresenter.Loaded event", scrollPresenterLoadedEvent);
                IdleSynchronizer.Wait();

                ScrollTo(scrollPresenter, 0.0, 600.0, ScrollingAnimationMode.Disabled, ScrollingSnapPointsMode.Ignore);

                RunOnUIThread.Execute(() =>
                {
                    Verify.AreEqual(600, scrollPresenter.VerticalOffset);

                    Log.Comment("ScrollPresenter.Content height is reduced by 300px. ScrollPresenter.VerticalOffset is expected to be reduced by 100px (600 -> 500).");
                    (scrollPresenter.Content as Grid).Height = 700;
                    if (reduceAnchorOffset)
                    {
                        Log.Comment("Tracked element is shifted up by 200px within the ScrollPresenter.Content (600 -> 400). Anchoring is expected to reduce the VerticalOffset by half of that (500 -> 400).");
                        anchorElement.Margin = new Thickness(0, 400, 0, 0);
                    }
                    scrollPresenterViewChangedEvent.Reset();
                });

                WaitForEvent("Waiting for ScrollPresenter.ViewChanged event", scrollPresenterViewChangedEvent);
                WaitForEvent("Waiting for ScrollPresenter.AnchorRequested event", scrollPresenterAnchorRequestedEvent);
                IdleSynchronizer.Wait();

                RunOnUIThread.Execute(() =>
                {
                    Verify.AreEqual(reduceAnchorOffset ? 400 : 500, scrollPresenter.VerticalOffset);

                    Log.Comment("ScrollPresenter CurrentAnchor is " + (scrollPresenter.CurrentAnchor == null ? "null" : "non-null"));
                    Verify.IsNotNull(scrollPresenter.CurrentAnchor);
                });
            }
        }
        private void AnchoringElementWithResizedViewport(Orientation orientation, double viewportSizeChange)
        {
            using (ScrollPresenterTestHooksHelper scrollPresenterTestHooksHelper = new ScrollPresenterTestHooksHelper(
                       enableAnchorNotifications: true,
                       enableInteractionSourcesNotifications: true,
                       enableExpressionAnimationStatusNotifications: false))
            {
                ScrollPresenter scrollPresenter                 = null;
                AutoResetEvent  scrollPresenterLoadedEvent      = new AutoResetEvent(false);
                AutoResetEvent  scrollPresenterViewChangedEvent = new AutoResetEvent(false);

                RunOnUIThread.Execute(() =>
                {
                    scrollPresenter = new ScrollPresenter();

                    SetupDefaultAnchoringUI(orientation, scrollPresenter, scrollPresenterLoadedEvent);
                });

                WaitForEvent("Waiting for Loaded event", scrollPresenterLoadedEvent);

                ZoomTo(scrollPresenter, 2.0f, 0.0f, 0.0f, ScrollingAnimationMode.Disabled, ScrollingSnapPointsMode.Ignore);

                double horizontalOffset = 0.0;
                double verticalOffset   = 0.0;

                RunOnUIThread.Execute(() =>
                {
                    if (orientation == Orientation.Vertical)
                    {
                        verticalOffset = (scrollPresenter.ExtentHeight * 2.0 - scrollPresenter.Height) / 2.0;
                        scrollPresenter.VerticalAnchorRatio = 0.5;
                    }
                    else
                    {
                        horizontalOffset = (scrollPresenter.ExtentWidth * 2.0 - scrollPresenter.Width) / 2.0;
                        scrollPresenter.HorizontalAnchorRatio = 0.5;
                    }
                });

                ScrollTo(scrollPresenter, horizontalOffset, verticalOffset, ScrollingAnimationMode.Disabled, ScrollingSnapPointsMode.Ignore, false /*hookViewChanged*/);

                RunOnUIThread.Execute(() =>
                {
                    Log.Comment("ScrollPresenter view prior to viewport size change: HorizontalOffset={0}, VerticalOffset={1}, ZoomFactor={2}",
                                scrollPresenter.HorizontalOffset, scrollPresenter.VerticalOffset, scrollPresenter.ZoomFactor);

                    scrollPresenter.ViewChanged += delegate(ScrollPresenter sender, object args)
                    {
                        Log.Comment("ViewChanged - HorizontalOffset={0}, VerticalOffset={1}, ZoomFactor={2}",
                                    sender.HorizontalOffset, sender.VerticalOffset, sender.ZoomFactor);
                        Log.Comment("ViewChanged - CurrentAnchor is " + (sender.CurrentAnchor == null ? "null" : "non-null"));
                        scrollPresenterViewChangedEvent.Set();
                    };

                    if (orientation == Orientation.Vertical)
                    {
                        Log.Comment("Changing viewport height");
                        scrollPresenter.Height += viewportSizeChange;
                    }
                    else
                    {
                        Log.Comment("Changing viewport width");
                        scrollPresenter.Width += viewportSizeChange;
                    }
                });

                WaitForEvent("Waiting for ScrollPresenter.ViewChanged event", scrollPresenterViewChangedEvent);
                IdleSynchronizer.Wait();

                RunOnUIThread.Execute(() =>
                {
                    Log.Comment("ScrollPresenter view after viewport size change: HorizontalOffset={0}, VerticalOffset={1}, ZoomFactor={2}",
                                scrollPresenter.HorizontalOffset, scrollPresenter.VerticalOffset, scrollPresenter.ZoomFactor);
                    Log.Comment("Expecting offset change equal to half the viewport size change");
                    if (orientation == Orientation.Vertical)
                    {
                        Verify.AreEqual(scrollPresenter.VerticalOffset, verticalOffset - viewportSizeChange / 2.0);
                    }
                    else
                    {
                        Verify.AreEqual(scrollPresenter.HorizontalOffset, horizontalOffset - viewportSizeChange / 2.0);
                    }

                    Log.Comment("ScrollPresenter CurrentAnchor is " + (scrollPresenter.CurrentAnchor == null ? "null" : "non-null"));
                    Verify.IsNotNull(scrollPresenter.CurrentAnchor);
                });
            }
        }
        private void AnchoringAtAlmostFarEdge(Orientation orientation)
        {
            using (ScrollPresenterTestHooksHelper scrollPresenterTestHooksHelper = new ScrollPresenterTestHooksHelper(
                       enableAnchorNotifications: true,
                       enableInteractionSourcesNotifications: true,
                       enableExpressionAnimationStatusNotifications: false))
            {
                ScrollPresenter scrollPresenter            = null;
                AutoResetEvent  scrollPresenterLoadedEvent = new AutoResetEvent(false);

                RunOnUIThread.Execute(() =>
                {
                    scrollPresenter = new ScrollPresenter();

                    SetupDefaultAnchoringUI(orientation, scrollPresenter, scrollPresenterLoadedEvent);
                });

                WaitForEvent("Waiting for Loaded event", scrollPresenterLoadedEvent);

                ZoomTo(scrollPresenter, 2.0f, 0.0f, 0.0f, ScrollingAnimationMode.Disabled, ScrollingSnapPointsMode.Ignore);

                double horizontalOffset = 0.0;
                double verticalOffset   = 0.0;

                RunOnUIThread.Execute(() =>
                {
                    if (orientation == Orientation.Vertical)
                    {
                        verticalOffset = scrollPresenter.ExtentHeight * 2.0 - scrollPresenter.Height - 1.0;
                        scrollPresenter.VerticalAnchorRatio = 1.0;
                    }
                    else
                    {
                        horizontalOffset = scrollPresenter.ExtentWidth * 2.0 - scrollPresenter.Width - 1.0;
                        scrollPresenter.HorizontalAnchorRatio = 1.0;
                    }
                });

                ScrollTo(scrollPresenter, horizontalOffset, verticalOffset, ScrollingAnimationMode.Disabled, ScrollingSnapPointsMode.Ignore, false /*hookViewChanged*/);

                RunOnUIThread.Execute(() =>
                {
                    Log.Comment("Inserting child at far edge");
                    InsertStackPanelChild((scrollPresenter.Content as Border).Child as StackPanel, 1 /*operationCount*/, c_defaultAnchoringUIStackPanelChildrenCount /*newIndex*/, 1 /*newCount*/);
                });

                IdleSynchronizer.Wait();

                RunOnUIThread.Execute(() =>
                {
                    Log.Comment("No ScrollPresenter offset change expected");
                    if (orientation == Orientation.Vertical)
                    {
                        Verify.AreEqual(scrollPresenter.VerticalOffset, verticalOffset);
                    }
                    else
                    {
                        Verify.AreEqual(scrollPresenter.HorizontalOffset, horizontalOffset);
                    }

                    Log.Comment("ScrollPresenter CurrentAnchor is " + (scrollPresenter.CurrentAnchor == null ? "null" : "non-null"));
                    Verify.IsNotNull(scrollPresenter.CurrentAnchor);
                });
            }
        }
        private void AnchoringAtFarEdgeWhileDecreasingViewport(Orientation orientation)
        {
            if (!PlatformConfiguration.IsOsVersionGreaterThanOrEqual(OSVersion.Redstone2))
            {
                Log.Comment("Skipping test on RS1 where InteractionTracker's AdjustPositionXIfGreaterThanThreshold/AdjustPositionYIfGreaterThanThreshold are ineffective in this scenario.");
                return;
            }

            using (ScrollPresenterTestHooksHelper scrollPresenterTestHooksHelper = new ScrollPresenterTestHooksHelper(
                       enableAnchorNotifications: true,
                       enableInteractionSourcesNotifications: true,
                       enableExpressionAnimationStatusNotifications: false))
            {
                ScrollPresenter scrollPresenter                 = null;
                AutoResetEvent  scrollPresenterLoadedEvent      = new AutoResetEvent(false);
                AutoResetEvent  scrollPresenterViewChangedEvent = new AutoResetEvent(false);

                RunOnUIThread.Execute(() =>
                {
                    scrollPresenter = new ScrollPresenter();

                    SetupDefaultAnchoringUI(orientation, scrollPresenter, scrollPresenterLoadedEvent);
                });

                WaitForEvent("Waiting for Loaded event", scrollPresenterLoadedEvent);

                ZoomTo(scrollPresenter, 2.0f, 0.0f, 0.0f, ScrollingAnimationMode.Disabled, ScrollingSnapPointsMode.Ignore);

                double horizontalOffset = 0.0;
                double verticalOffset   = 0.0;

                RunOnUIThread.Execute(() =>
                {
                    if (orientation == Orientation.Vertical)
                    {
                        verticalOffset = scrollPresenter.ExtentHeight * 2.0 - scrollPresenter.Height;
                        scrollPresenter.VerticalAnchorRatio = 1.0;
                    }
                    else
                    {
                        horizontalOffset = scrollPresenter.ExtentWidth * 2.0 - scrollPresenter.Width;
                        scrollPresenter.HorizontalAnchorRatio = 1.0;
                    }
                });

                ScrollTo(scrollPresenter, horizontalOffset, verticalOffset, ScrollingAnimationMode.Disabled, ScrollingSnapPointsMode.Ignore, false /*hookViewChanged*/);

                RunOnUIThread.Execute(() =>
                {
                    scrollPresenter.ViewChanged += delegate(ScrollPresenter sender, object args)
                    {
                        Log.Comment("ViewChanged - HorizontalOffset={0}, VerticalOffset={1}, ZoomFactor={2}",
                                    sender.HorizontalOffset, sender.VerticalOffset, sender.ZoomFactor);
                        Log.Comment("ViewChanged - CurrentAnchor is " + (sender.CurrentAnchor == null ? "null" : "non-null"));
                        scrollPresenterViewChangedEvent.Set();
                    };

                    scrollPresenter.AnchorRequested += delegate(ScrollPresenter sender, ScrollingAnchorRequestedEventArgs args)
                    {
                        Log.Comment("AnchorRequested - AnchorCandidates.Count={0}", args.AnchorCandidates.Count);
                    };

                    if (orientation == Orientation.Vertical)
                    {
                        Log.Comment("Decreasing viewport height");
                        scrollPresenter.Height -= 100;
                    }
                    else
                    {
                        Log.Comment("Decreasing viewport width");
                        scrollPresenter.Width -= 100;
                    }
                });

                WaitForEvent("Waiting for ScrollPresenter.ViewChanged event", scrollPresenterViewChangedEvent);
                IdleSynchronizer.Wait();

                RunOnUIThread.Execute(() =>
                {
                    if (orientation == Orientation.Vertical)
                    {
                        verticalOffset = scrollPresenter.ExtentHeight * 2.0 - scrollPresenter.Height;
                    }
                    else
                    {
                        horizontalOffset = scrollPresenter.ExtentWidth * 2.0 - scrollPresenter.Width;
                    }

                    Log.Comment("ScrollPresenter offset change expected");
                    Verify.AreEqual(scrollPresenter.HorizontalOffset, horizontalOffset);
                    Verify.AreEqual(scrollPresenter.VerticalOffset, verticalOffset);

                    Log.Comment("ScrollPresenter CurrentAnchor is " + (scrollPresenter.CurrentAnchor == null ? "null" : "non-null"));
                    Verify.IsNull(scrollPresenter.CurrentAnchor);
                });
            }
        }
예제 #8
0
        private void AnchoringAtFarEdgeWhileIncreasingContent(Orientation orientation, double viewportSizeChange, double expectedFinalOffset)
        {
            if (!PlatformConfiguration.IsOsVersionGreaterThanOrEqual(OSVersion.Redstone2))
            {
                Log.Comment("Skipping test on RS1 where InteractionTracker's AdjustPositionXIfGreaterThanThreshold/AdjustPositionYIfGreaterThanThreshold are ineffective in this scenario.");
                return;
            }

            using (ScrollPresenterTestHooksHelper scrollPresenterTestHooksHelper = new ScrollPresenterTestHooksHelper(
                       enableAnchorNotifications: true,
                       enableInteractionSourcesNotifications: true,
                       enableExpressionAnimationStatusNotifications: false))
            {
                ScrollPresenter scrollPresenter                 = null;
                AutoResetEvent  scrollPresenterLoadedEvent      = new AutoResetEvent(false);
                AutoResetEvent  scrollPresenterViewChangedEvent = new AutoResetEvent(false);

                RunOnUIThread.Execute(() =>
                {
                    scrollPresenter = new ScrollPresenter();

                    SetupDefaultAnchoringUI(orientation, scrollPresenter, scrollPresenterLoadedEvent);
                });

                WaitForEvent("Waiting for Loaded event", scrollPresenterLoadedEvent);

                ZoomTo(scrollPresenter, 2.0f, 0.0f, 0.0f, AnimationMode.Disabled, SnapPointsMode.Ignore);

                double horizontalOffset = 0.0;
                double verticalOffset   = 0.0;

                RunOnUIThread.Execute(() =>
                {
                    if (orientation == Orientation.Vertical)
                    {
                        verticalOffset = scrollPresenter.ExtentHeight * 2.0 - scrollPresenter.Height;
                        scrollPresenter.VerticalAnchorRatio = 1.0;
                    }
                    else
                    {
                        horizontalOffset = scrollPresenter.ExtentWidth * 2.0 - scrollPresenter.Width;
                        scrollPresenter.HorizontalAnchorRatio = 1.0;
                    }
                });

                ScrollTo(scrollPresenter, horizontalOffset, verticalOffset, AnimationMode.Disabled, SnapPointsMode.Ignore, false /*hookViewChanged*/);

                RunOnUIThread.Execute(() =>
                {
                    scrollPresenter.ViewChanged += delegate(ScrollPresenter sender, object args)
                    {
                        Log.Comment("ViewChanged - HorizontalOffset={0}, VerticalOffset={1}, ZoomFactor={2}",
                                    sender.HorizontalOffset, sender.VerticalOffset, sender.ZoomFactor);
                        if ((orientation == Orientation.Vertical && expectedFinalOffset == sender.VerticalOffset) ||
                            (orientation == Orientation.Horizontal && expectedFinalOffset == sender.HorizontalOffset))
                        {
                            scrollPresenterViewChangedEvent.Set();
                        }
                    };

                    Log.Comment("Inserting child at far edge");
                    InsertStackPanelChild((scrollPresenter.Content as Border).Child as StackPanel, 1 /*operationCount*/, c_defaultAnchoringUIStackPanelChildrenCount /*newIndex*/, 1 /*newCount*/);

                    if (viewportSizeChange != 0)
                    {
                        if (orientation == Orientation.Vertical)
                        {
                            Log.Comment("Changing viewport height");
                            scrollPresenter.Height += viewportSizeChange;
                        }
                        else
                        {
                            Log.Comment("Changing viewport width");
                            scrollPresenter.Width += viewportSizeChange;
                        }
                    }
                });

                WaitForEvent("Waiting for ScrollPresenter.ViewChanged event", scrollPresenterViewChangedEvent);
                IdleSynchronizer.Wait();

                RunOnUIThread.Execute(() =>
                {
                    if (orientation == Orientation.Vertical)
                    {
                        verticalOffset = scrollPresenter.ExtentHeight * 2.0 - scrollPresenter.Height;
                    }
                    else
                    {
                        horizontalOffset = scrollPresenter.ExtentWidth * 2.0 - scrollPresenter.Width;
                    }

                    Log.Comment("ScrollPresenter offset change expected");
                    Verify.AreEqual(scrollPresenter.HorizontalOffset, horizontalOffset);
                    Verify.AreEqual(scrollPresenter.VerticalOffset, verticalOffset);
                });
            }
        }