Esempio n. 1
0
        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);
            });
        }
Esempio n. 2
0
        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);
            });
        }
Esempio n. 3
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);
            });
        }
Esempio n. 4
0
        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);
            });
        }
Esempio n. 5
0
        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);
        }
Esempio n. 6
0
        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);
        }
Esempio n. 7
0
        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);
        }
Esempio n. 8
0
        // [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));
        }