public void CanRemoveAndInsertItemsInRealizedRange() { RunOnUIThread.Execute(() => { var dataSource = new CustomItemsSource(Enumerable.Range(0, 3).ToList()); var repeater = SetupRepeater(dataSource); var realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(3, realized); Log.Comment("Remove index 1 in realized range"); dataSource.Remove(index: 1, count: 1, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(2, realized); Log.Comment("Add 5 items at index 1"); dataSource.Insert(index: 1, count: 5, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(3, realized); }); }
public void ValidateInserts() { RunOnUIThread.Execute(() => { var dataSource = new CustomItemsSource(Enumerable.Range(0, 10).ToList()); var repeater = SetupRepeater(dataSource); Log.Comment("Insert in realized range: Inserting 3 items at index 4"); dataSource.Insert(index: 4, count: 3, reset: false); repeater.UpdateLayout(); var realized = VerifyRealizedRange(repeater, dataSource); Verify.IsGreaterThan(realized, 0); Log.Comment("Insert before realized range: Inserting 3 items at index 0"); dataSource.Insert(index: 0, count: 3, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.IsGreaterThan(realized, 0); Log.Comment("Insert after realized range: Inserting 3 items at index 10"); dataSource.Insert(index: 10, count: 3, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.IsGreaterThan(realized, 0); }); }
public void CanRemoveItemsStartingInRealizedRange() { RunOnUIThread.Execute(() => { var dataSource = new CustomItemsSource(Enumerable.Range(0, 10).ToList()); var repeater = SetupRepeater(dataSource); var realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(3, realized); Log.Comment("Remove in realized range: start:(1)InView end:(3)InView."); dataSource.Remove(index: 1, count: 3, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(3, realized); Log.Comment("Remove in realized range: start:(1)InView end:(6)InView."); dataSource.Remove(index: 1, count: 6, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(1, realized); }); }
public void CanRemoveItemsStartingBeforeRealizedRange() { CustomItemsSource dataSource = null; RunOnUIThread.Execute(() => dataSource = new CustomItemsSource(Enumerable.Range(0, 20).ToList())); ScrollViewer scrollViewer = null; ItemsRepeater repeater = null; var viewChangedEvent = new ManualResetEvent(false); RunOnUIThread.Execute(() => { repeater = SetupRepeater(dataSource, ref scrollViewer); scrollViewer.ViewChanged += (sender, args) => { if (!args.IsIntermediate) { viewChangedEvent.Set(); } }; scrollViewer.ChangeView(null, 600, null, true); }); Verify.IsTrue(viewChangedEvent.WaitOne(DefaultWaitTime), "Waiting for ViewChanged."); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Log.Comment("Remove before realized range: start:(0)beforeView end:(1)beforeView."); dataSource.Remove(index: 0, count: 2, reset: false); repeater.UpdateLayout(); var realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(4, realized); Log.Comment("Remove before realized range: start:(0)beforeView end:(4)inview."); dataSource.Remove(index: 0, count: 5, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(3, realized); Log.Comment("Insert before realized range: Inserting 10 items at index 0"); dataSource.Insert(index: 0, count: 10, reset: false); repeater.UpdateLayout(); VerifyRealizedRange(repeater, dataSource); Log.Comment("Insert after realized range: Inserting 10 items at index 19"); dataSource.Insert(index: 19, count: 10, reset: false); repeater.UpdateLayout(); VerifyRealizedRange(repeater, dataSource); Log.Comment("Remove before realized range: start:(5)beforeView end:(25)afterView."); dataSource.Remove(index: 5, count: 20, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.IsLessThanOrEqual(3, realized); }); }
private int VerifyRealizedRange(ItemsRepeater repeater, CustomItemsSource dataSource) { int numRealized = 0; // trace Log.Comment("index:ItemsSourceView:Item"); for (int i = 0; i < dataSource.Inner.Count; i++) { var element = repeater.TryGetElement(i); if (element != null) { var data = ((TextBlock)element).Text; Log.Comment("{0} {1}:[{2}]", i, dataSource.GetAt(i), data); numRealized++; } else { Log.Comment(i + ":[null]"); } } // verify for (int i = 0; i < dataSource.Inner.Count; i++) { var element = repeater.TryGetElement(i); if (element != null) { var data = ((TextBlock)element).Text; Verify.AreEqual(dataSource.GetAt(i).ToString(), data); } } return(numRealized); }
private ItemsRepeater SetupRepeater(CustomItemsSource dataSource, ElementFactory elementFactory, ref ScrollViewer scrollViewer, VirtualizingLayout layout) { var repeater = new ItemsRepeater() { ItemsSource = dataSource, ItemTemplate = elementFactory, Layout = layout, VerticalCacheLength = 0, HorizontalCacheLength = 0 }; scrollViewer = new ScrollViewer { Content = repeater }; Content = new ItemsRepeaterScrollHost() { Width = 200, Height = 200, ScrollViewer = scrollViewer }; Content.UpdateLayout(); if (dataSource.Count > 0) { int realized = VerifyRealizedRange(repeater, dataSource); Verify.IsGreaterThan(realized, 0); } return(repeater); }
private ItemsRepeater SetupRepeater(CustomItemsSource dataSource, ElementFactory elementFactory, ref ScrollViewer scrollViewer, VirtualizingLayout layout) { var repeater = new ItemsRepeater() { ItemsSource = dataSource, #if BUILD_WINDOWS ItemTemplate = (Windows.UI.Xaml.IElementFactory)elementFactory, #else ItemTemplate = elementFactory, #endif Layout = layout, VerticalCacheLength = 0, HorizontalCacheLength = 0 }; scrollViewer = new ScrollViewer { Content = repeater }; Content = new ScrollAnchorProvider() { Width = 200, Height = 200, Content = scrollViewer }; Content.UpdateLayout(); int realized = VerifyRealizedRange(repeater, dataSource); Verify.IsGreaterThan(realized, 0); return(repeater); }
// [TestMethod] Issue 1018 public void ValidateFocusMoveOnElementClearedWithUniqueIds() { ItemsRepeater repeater = null; CustomItemsSource dataSource = null; RunOnUIThread.Execute(() => { dataSource = new CustomItemsSourceWithUniqueId(Enumerable.Range(0, 5).ToList()); }); repeater = SetupRepeater(dataSource, "<Button Content='{Binding}' Height='10' />"); // dataSource: 0 1 2 3 4 // Index 0 deleted, focus should be on the new element which has index 0 SharedHelpers.RunActionsWithWait( new Action[] { () => { MoveFocusToIndex(repeater, 0); }, () => { dataSource.Remove(0 /* index */, 1 /* count */, true /* reset*/); }, () => { ValidateCurrentFocus(repeater, 0 /*expectedIndex */, "1" /* expectedContent */); } }); // dataSource: 1 2 3 4 // Last element deleted, focus should move to the previous element int lastIndex = dataSource.Inner.Count - 1; SharedHelpers.RunActionsWithWait( new Action[] { () => { MoveFocusToIndex(repeater, lastIndex); }, () => { dataSource.Remove(lastIndex /* index */, 1 /* count */, true /* reset*/); }, () => { ValidateCurrentFocus(repeater, 2 /*expectedIndex */, "3" /* expectedContent */); } }); // dataSource: 1 2 3 // Reset should keep the focused element as long as the unique id matches. SharedHelpers.RunActionsWithWait( new Action[] { () => { MoveFocusToIndex(repeater, 0); }, () => { dataSource.Reset(); }, () => { int newIndex = dataSource.Inner.IndexOf(1); ValidateCurrentFocus(repeater, newIndex /*expectedIndex */, "1" /* expectedContent */); } }); // dataSource: 1 2 3 // Remove multiple elements SharedHelpers.RunActionsWithWait( new Action[] { () => { MoveFocusToIndex(repeater, 0); }, () => { dataSource.Remove(0 /* index */, 2 /* count */, true /* reset*/); }, () => { ValidateCurrentFocus(repeater, 0 /*expectedIndex */, "3" /* expectedContent */); } }); }
public void ValidateElementEvents() { CustomItemsSource dataSource = null; RunOnUIThread.Execute(() => dataSource = new CustomItemsSource(Enumerable.Range(0, 10).ToList())); var repeater = SetupRepeater(dataSource); RunOnUIThread.Execute(() => { List <int> preparedIndices = new List <int>(); List <int> clearedIndices = new List <int>(); List <KeyValuePair <int, int> > changedIndices = new List <KeyValuePair <int, int> >(); repeater.ElementPrepared += (sender, args) => { preparedIndices.Add(args.Index); }; repeater.ElementClearing += (sender, args) => { clearedIndices.Add(sender.GetElementIndex(args.Element)); }; repeater.ElementIndexChanged += (sender, args) => { changedIndices.Add(new KeyValuePair <int, int>(args.OldIndex, args.NewIndex)); }; Log.Comment("Insert in realized range: Inserting 1 item at index 1"); dataSource.Insert(index: 1, count: 1, reset: false); repeater.UpdateLayout(); Verify.AreEqual(1, preparedIndices.Count); Verify.AreEqual(1, preparedIndices[0]); Verify.AreEqual(2, changedIndices.Count); Verify.IsTrue(changedIndices.Contains(new KeyValuePair <int, int>(1, 2))); Verify.IsTrue(changedIndices.Contains(new KeyValuePair <int, int>(2, 3))); Verify.AreEqual(1, clearedIndices.Count); Verify.AreEqual(3, clearedIndices[0]); preparedIndices.Clear(); clearedIndices.Clear(); changedIndices.Clear(); Log.Comment("Remove in realized range: Removing 1 item at index 0"); dataSource.Remove(index: 0, count: 1, reset: false); repeater.UpdateLayout(); Verify.AreEqual(1, clearedIndices.Count); Verify.AreEqual(0, clearedIndices[0]); Verify.AreEqual(1, preparedIndices.Count); Verify.AreEqual(2, preparedIndices[0]); Verify.AreEqual(2, changedIndices.Count); Verify.IsTrue(changedIndices.Contains(new KeyValuePair <int, int>(1, 0))); Verify.IsTrue(changedIndices.Contains(new KeyValuePair <int, int>(2, 1))); }); }
public void CanMoveItem() { CustomItemsSource dataSource = null; RunOnUIThread.Execute(() => dataSource = new CustomItemsSource(Enumerable.Range(0, 10).ToList())); ScrollViewer scrollViewer = null; ItemsRepeater repeater = null; var viewChangedEvent = new ManualResetEvent(false); RunOnUIThread.Execute(() => { repeater = SetupRepeater(dataSource, ref scrollViewer); scrollViewer.ScrollChanged += (sender, args) => { if (args.HorizontalChange != 0 || args.VerticalChange != 0) { viewChangedEvent.Set(); } }; scrollViewer.ChangeView(null, 400, null, true); }); Verify.IsTrue(viewChangedEvent.WaitOne(DefaultWaitTime), "Waiting for ViewChanged."); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { var realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(4, realized); Log.Comment("Move before realized range."); dataSource.Move(oldIndex: 0, newIndex: 1, count: 2, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(4, realized); Log.Comment("Move in realized range."); dataSource.Move(oldIndex: 3, newIndex: 5, count: 2, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(4, realized); Log.Comment("Move after realized range"); dataSource.Move(oldIndex: 7, newIndex: 8, count: 2, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(4, realized); }); }
public void CanReplaceSingleItem() { CustomItemsSource dataSource = null; RunOnUIThread.Execute(() => dataSource = new CustomItemsSource(Enumerable.Range(0, 10).ToList())); ScrollViewer scrollViewer = null; ItemsRepeater repeater = null; var viewChangedEvent = new ManualResetEvent(false); RunOnUIThread.Execute(() => { repeater = SetupRepeater(dataSource, ref scrollViewer); scrollViewer.ViewChanged += (sender, args) => { if (!args.IsIntermediate) { viewChangedEvent.Set(); } }; scrollViewer.ChangeView(null, 200, null, true); }); Verify.IsTrue(viewChangedEvent.WaitOne(DefaultWaitTime), "Waiting for ViewChanged."); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { var realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(4, realized); Log.Comment("Replace before realized range."); dataSource.Replace(index: 0, oldCount: 1, newCount: 1, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(4, realized); Log.Comment("Replace in realized range."); dataSource.Replace(index: 2, oldCount: 1, newCount: 1, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(4, realized); Log.Comment("Replace after realized range"); dataSource.Replace(index: 8, oldCount: 1, newCount: 1, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(4, realized); }); }
public void ValidateClear() { RunOnUIThread.Execute(() => { var dataSource = new CustomItemsSource(Enumerable.Range(0, 3).ToList()); var repeater = SetupRepeater(dataSource, new FlowLayout()); Log.Comment("Clear the collection"); dataSource.Clear(); repeater.UpdateLayout(); var realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(0, realized); }); }
public void ValidateRegularResets() { RunOnUIThread.Execute(() => { var dataSource = new CustomItemsSource(Enumerable.Range(0, 3).ToList()); var repeater = SetupRepeater(dataSource); Log.Comment("Reset collection"); dataSource.GetAtCallCount = 0; dataSource.Reset(); repeater.UpdateLayout(); // Make sure data was requested because during a normal reset elements (already bound with data) are not reused. Verify.AreEqual(3, dataSource.GetAtCallCount); var realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(3, realized); }); }
public void VerifyElement0OwnershipInUniformGridLayout() { CustomItemsSource dataSource = null; RunOnUIThread.Execute(() => dataSource = new CustomItemsSource(new List <int>())); ItemsRepeater repeater = null; int elementsCleared = 0; int elementsPrepared = 0; RunOnUIThread.Execute(() => { repeater = SetupRepeater(dataSource, new UniformGridLayout()); repeater.ElementPrepared += (sender, args) => { elementsPrepared++; }; repeater.ElementClearing += (sender, args) => { elementsCleared++; }; }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { Log.Comment("Add two item"); dataSource.Insert(index: 0, count: 1, reset: false); dataSource.Insert(index: 1, count: 1, reset: false); repeater.UpdateLayout(); var realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(2, realized); Log.Comment("replace the first item"); dataSource.Replace(index: 0, oldCount: 1, newCount: 1, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(2, realized); Log.Comment("Remove two items"); dataSource.Remove(index: 1, count: 1, reset: false); dataSource.Remove(index: 0, count: 1, reset: false); repeater.UpdateLayout(); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(0, realized); Verify.AreEqual(elementsPrepared, elementsCleared); }); }
public void EnsureReplaceOfAnchorDoesNotResetAllContainers() { CustomItemsSource dataSource = null; RunOnUIThread.Execute(() => dataSource = new CustomItemsSource(Enumerable.Range(0, 10).ToList())); ScrollViewer scrollViewer = null; ItemsRepeater repeater = null; var viewChangedEvent = new ManualResetEvent(false); int elementsCleared = 0; int elementsPrepared = 0; RunOnUIThread.Execute(() => { repeater = SetupRepeater(dataSource, ref scrollViewer); repeater.ElementPrepared += (sender, args) => { elementsPrepared++; }; repeater.ElementClearing += (sender, args) => { elementsCleared++; }; }); IdleSynchronizer.Wait(); RunOnUIThread.Execute(() => { var realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(3, realized); Log.Comment("Replace anchor element 0"); elementsPrepared = 0; elementsCleared = 0; dataSource.Replace(index: 0, oldCount: 1, newCount: 1, reset: false); repeater.UpdateLayout(); Verify.AreEqual(1, elementsPrepared); Verify.AreEqual(1, elementsCleared); realized = VerifyRealizedRange(repeater, dataSource); Verify.AreEqual(3, realized); }); }
public void ValidateSentinelsDuringInserts() { RunOnUIThread.Execute(() => { var dataSource = new CustomItemsSource(Enumerable.Range(0, 10).ToList()); int getElementCallCount = 0; int recycleElementCallCount = 0; var elementFactory = new RecyclingElementFactoryDerived() { Templates = { { "key", SharedHelpers.GetDataTemplate("<TextBlock Text='{Binding}' Height='100' />") } }, RecyclePool = new RecyclePool(), GetElementFunc = (int index, UIElement owner, UIElement elementFromBase) => { getElementCallCount++; return(elementFromBase); }, ClearElementFunc = (UIElement element, UIElement owner) => recycleElementCallCount++, ValidateElementIndices = false }; var repeater = SetupRepeater(dataSource, elementFactory); getElementCallCount = 0; recycleElementCallCount = 0; Log.Comment("Insert in realized range: Inserting 100 items at index 1"); dataSource.Insert(index: 1, count: 100, reset: false); repeater.UpdateLayout(); var realized = VerifyRealizedRange(repeater, dataSource); Verify.IsGreaterThan(realized, 0); Verify.IsLessThan(getElementCallCount, 6); Verify.IsLessThan(recycleElementCallCount, 6); }); }
private ItemsRepeater SetupRepeater(CustomItemsSource dataSource, ref ScrollViewer scrollViewer) { return(SetupRepeater(dataSource, GetElementFactory(), ref scrollViewer, new StackLayout())); }
private ItemsRepeater SetupRepeater(CustomItemsSource dataSource, ElementFactory elementFactory = null) { ScrollViewer sv = null; return(SetupRepeater(dataSource, elementFactory, ref sv, new StackLayout())); }
private ItemsRepeater SetupRepeater(CustomItemsSource dataSource, VirtualizingLayout layout) { ScrollViewer sv = null; return(SetupRepeater(dataSource, GetElementFactory(), ref sv, layout)); }