private void RunElementTrackingTestRoutine(Action < ObservableCollection <ObservableCollection <string> > /* data */, TestScrollingSurface[] /* scrollers */, ItemsRepeater /* rootRepeater */> testRoutine) { // Base setup for our element tracking tests. // We have 4 fake scrollers in series, initially in a non scrollable configuration. // Under them we have a group repeater tree (2 groups with 3 items each). // The group UI is a StackPanel with a TextBlock "header" and an inner ItemsRepeater. RunOnUIThread.Execute(() => { int groupCount = 2; int itemsPerGroup = 3; var data = new ObservableCollection <ObservableCollection <string> >( Enumerable.Range(0, groupCount).Select(i => new ObservableCollection <string>( Enumerable.Range(0, itemsPerGroup).Select(j => string.Format("Item #{0}.{1}", i, j))))); var itemElements = Enumerable.Range(0, groupCount).Select(i => Enumerable.Range(0, itemsPerGroup).Select(j => new Border { Tag = data[i][j], Width = 50, Height = 50, Background = new SolidColorBrush(Colors.Red) }).ToList()).ToArray(); var headerElements = Enumerable.Range(0, groupCount).Select(i => new TextBlock { Text = "Header #" + i }).ToList(); var groupRepeaters = Enumerable.Range(0, groupCount).Select(i => new ItemsRepeater { Tag = "ItemsRepeater #" + i, ItemsSource = data[i], ItemTemplate = MockElementFactory.CreateElementFactory(itemElements[i]), Layout = new TestGridLayout { Orientation = Orientation.Horizontal, MinItemWidth = 50, MinItemHeight = 50, MinRowSpacing = 10, MinColumnSpacing = 10 } }).ToList(); var groupElement = Enumerable.Range(0, groupCount).Select(i => { var panel = new StackPanel(); panel.Tag = "Group #" + i; panel.Children.Add(headerElements[i]); panel.Children.Add(groupRepeaters[i]); return(panel); }).ToList(); var rootRepeater = new ItemsRepeater { Tag = "Root ItemsRepeater", ItemsSource = data, ItemTemplate = MockElementFactory.CreateElementFactory(groupElement), Layout = new TestStackLayout { Orientation = Orientation.Vertical } }; var scrollers = new TestScrollingSurface[4]; for (int i = 0; i < scrollers.Length; ++i) { scrollers[i] = new TestScrollingSurface() { Tag = "S" + i, Content = i > 0 ? (UIElement)scrollers[i - 1] : rootRepeater }; } var resetScrollers = (Action)(() => { foreach (var scroller in scrollers) { scroller.IsHorizontallyScrollable = false; scroller.IsVerticallyScrollable = false; scroller.RegisterAnchorCandidateFunc = null; scroller.UnregisterAnchorCandidateFunc = null; scroller.GetRelativeViewportFunc = null; } }); var outerScroller = scrollers.Last(); outerScroller.Width = 200.0; outerScroller.Height = 2000.0; Content = outerScroller; Content.UpdateLayout(); testRoutine(data, scrollers, rootRepeater); }); }