// [TestMethod] Temporarily disabled for bug 18866003 public void ValidateItemsRepeaterScrollHostScenario() { var realizationRects = new List <Rect>(); var scrollViewer = (ScrollViewer)null; var viewChangedEvent = new ManualResetEvent(false); int waitTime = 2000; // 2 seconds RunOnUIThread.Execute(() => { var repeater = new ItemsRepeater() { Layout = GetMonitoringLayout(new Size(500, 600), realizationRects), HorizontalCacheLength = 0.0, VerticalCacheLength = 0.0 }; scrollViewer = new ScrollViewer { Content = repeater, HorizontalScrollBarVisibility = ScrollBarVisibility.Hidden, VerticalScrollBarVisibility = ScrollBarVisibility.Hidden, }; scrollViewer.ViewChanged += (sender, args) => { if (!args.IsIntermediate) { viewChangedEvent.Set(); } }; var tracker = new ItemsRepeaterScrollHost() { Width = 200, Height = 300, ScrollViewer = scrollViewer }; Content = tracker; Content.UpdateLayout(); // First layout pass will invalidate measure during the first arrange // so that we can get a viewport during the second measure/arrange pass. // That's why Measure gets invoked twice. // After that, ScrollViewer.SizeChanged is raised and it also invalidates // layout (third pass). Verify.AreEqual(3, realizationRects.Count); Verify.AreEqual(new Rect(0, 0, 0, 0), realizationRects[0]); Verify.AreEqual(new Rect(0, 0, 200, 300), realizationRects[1]); Verify.AreEqual(new Rect(0, 0, 200, 300), realizationRects[2]); realizationRects.Clear(); viewChangedEvent.Reset(); scrollViewer.ChangeView(null, 100.0, 1.0f, disableAnimation: true); }); Verify.IsTrue(viewChangedEvent.WaitOne(waitTime), "Waiting for view changed"); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Verify.AreEqual(new Rect(0, 100, 200, 300), realizationRects.Last()); realizationRects.Clear(); viewChangedEvent.Reset(); // Max viewport offset is (300, 400). Horizontal viewport offset // is expected to get coerced from 400 to 300. scrollViewer.ChangeView(400, 100.0, 1.0f, disableAnimation: true); }); Verify.IsTrue(viewChangedEvent.WaitOne(waitTime), "Waiting for view changed"); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Verify.AreEqual(new Rect(300, 100, 200, 300), realizationRects.Last()); realizationRects.Clear(); viewChangedEvent.Reset(); scrollViewer.ChangeView(null, null, 2.0f, disableAnimation: true); }); Verify.IsTrue(viewChangedEvent.WaitOne(waitTime), "Waiting for view changed"); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Verify.AreEqual(new Rect(300, 100, 100, 150), realizationRects.Last()); realizationRects.Clear(); }); }
public void BringIntoViewOfExistingItemsDoesNotChangeScrollOffset() { System.Windows.Controls.ScrollViewerEx scrollViewer = null; ItemsRepeater repeater = null; AutoResetEvent scrollViewerScrolledEvent = new AutoResetEvent(false); RunOnUIThread.Execute(() => { repeater = new ItemsRepeater(); repeater.ItemsSource = Enumerable.Range(0, 100).Select(x => x.ToString()).ToList(); scrollViewer = new System.Windows.Controls.ScrollViewerEx() { Content = repeater, MaxHeight = 400, MaxWidth = 200 }; Content = scrollViewer; Content.UpdateLayout(); }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Log.Comment("Scroll to end"); scrollViewer.ViewChanged += (object sender, ScrollViewerViewChangedEventArgs e) => { if (!e.IsIntermediate) { Log.Comment("ScrollViewer scrolling finished"); scrollViewerScrolledEvent.Set(); } }; scrollViewer.ChangeView(null, repeater.ActualHeight, null); scrollViewer.UpdateLayout(); }); Log.Comment("Wait for scrolling"); if (Debugger.IsAttached) { scrollViewerScrolledEvent.WaitOne(); } else { if (!scrollViewerScrolledEvent.WaitOne(TimeSpan.FromMilliseconds(5000))) { throw new Exception("Timeout expiration in WaitForEvent."); } } IdleSynchronizer.Wait(); double endOfScrollOffset = 0; RunOnUIThread.Execute(() => { Log.Comment("Determine scrolled offset"); endOfScrollOffset = scrollViewer.VerticalOffset; // Idea: we might not have scrolled to the end, however we should at least have moved so much that the end is not too far away Verify.IsTrue(Math.Abs(endOfScrollOffset - repeater.ActualHeight) < 500, $"We should at least have scrolled some amount. " + $"ScrollOffset:{endOfScrollOffset} Repeater height: {repeater.ActualHeight}"); var lastItem = (FrameworkElement)repeater.GetOrCreateElement(99); lastItem.UpdateLayout(); Log.Comment("Bring last element into view"); lastItem.BringIntoView(); }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Log.Comment("Verify position did not change"); Verify.IsTrue(Math.Abs(endOfScrollOffset - scrollViewer.VerticalOffset) < 1); }); }