protected override sealed void OnItemsChanged(object sender, ItemsChangedEventArgs args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            var owner = ItemsOwner;
            var items = owner != null ? owner.Items : null;

            var action = args.Action;
            if (action == NotifyCollectionChangedAction.Reset)
            {
                OnItemsChanged(items, new NotifyCollectionChangedEventArgs(action));
            }
            else if (items != null)
            {
                var generator = sender as IItemContainerGenerator;
                if (generator != null)
                {
                    if (action == NotifyCollectionChangedAction.Add)
                    {
                        var index = generator.IndexFromGeneratorPosition(args.Position);
                        // ItemContainerGenerator is infested with bugs. One of which is that as items are added to the end of a collection, the index from IndexFromGeneratorPosition will usually be wrong.
                        if (args.Position.Offset == 1)
                        {
                            index = items.Count - 1;
                        }
                        var newItems = new VirtualItemsList(items, index, args.ItemCount);

                        if (!IsVirtualizing)
                        {
                            for (int i = index; i < index + args.ItemCount; i++)
                            {
                                RealizeItem(i);
                            }
                        }

                        OnItemsChanged(items, new NotifyCollectionChangedEventArgs(action, newItems, index));
                    }
                    else if (action == NotifyCollectionChangedAction.Remove)
                    {
                        var oldIndex = generator.IndexFromGeneratorPosition(args.Position);
                        var oldItems = new ArrayList(args.ItemCount);
                        // Since we can't actually get the old items directly, and sometimes we can't even get the old index from the generator, we'll get as many as we can from the visuals.
                        for (int i = 0; i < args.ItemUICount; i++)
                        {
                            var element = InternalChildren[args.Position.Index + i];
                            oldItems.Add(ItemFromContainer(element));
                            if (oldIndex == -1)
                            {
                                oldIndex = (int)element.ReadLocalValue(IndexForItemContainerProperty);

                            }
                            element.ClearValue(IndexForItemContainerProperty);
                        }

                        // Unfortunately ItemContainerGenerator always expects us to remove the child, even if we didn't want to.
                        if (args.ItemUICount > 0)
                        {
                            RemoveInternalChildRange(args.Position.Index, args.ItemUICount);

                        }
                        // HACK ($$$) - the position generating logic is returning the wrong position
                        // the position generated for the last item is beyond the bounds of the collection
                        // causing "RemoveRange" to fail
                        int indexToRemove = (oldIndex > args.Position.Index) ? args.Position.Index : oldIndex;
                        OnItemsChanged(items, new NotifyCollectionChangedEventArgs(action, oldItems, indexToRemove));
                    }
                    else if (action == NotifyCollectionChangedAction.Move)
                    {
                        var oldIndex = -1;
                        var index = generator.IndexFromGeneratorPosition(args.Position);
                        var movedItems = new VirtualItemsList(items, index, args.ItemCount);

                        var count = args.ItemUICount;
                        if (count > 0)
                        {
                            var elements = new UIElement[count];
                            for (var i = 0; i < count; i++)
                            {
                                elements[i] = InternalChildren[args.OldPosition.Index + i];
                                if (oldIndex == -1)
                                {
                                    oldIndex = (int)elements[i].ReadLocalValue(IndexForItemContainerProperty);
                                }
                            }
                            RemoveInternalChildRange(args.OldPosition.Index + Math.Min(args.OldPosition.Offset, 1), count);
                            for (var i = 0; i < count; i++)
                            {
                                InsertInternalChild(args.Position.Index + i, elements[i]);
                            }
                        }

                        OnItemsChanged(items, new NotifyCollectionChangedEventArgs(action, movedItems, index, oldIndex));
                    }
                    else if (action == NotifyCollectionChangedAction.Replace)
                    {
                        var index = generator.IndexFromGeneratorPosition(args.Position);
                        var newItems = new VirtualItemsList(items, index, args.ItemCount);
                        // Todo: Actually get the old items.  ItemContainerGenerator doesn't make this easy.
                        var oldItems = new VirtualItemsList(null, index, args.ItemCount);

                        OnItemsChanged(items, new NotifyCollectionChangedEventArgs(action, newItems, oldItems, index));
                    }
                }
            }

            base.OnItemsChanged(sender, args);

            InvalidateReality();
        }
Beispiel #2
0
        protected override sealed void OnItemsChanged(object sender, ItemsChangedEventArgs args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }

            var owner = ItemsOwner;
            var items = owner != null ? owner.Items : null;

            var action = args.Action;

            if (action == NotifyCollectionChangedAction.Reset)
            {
                OnItemsChanged(items, new NotifyCollectionChangedEventArgs(action));
            }
            else if (items != null)
            {
                var generator = sender as IItemContainerGenerator;
                if (generator != null)
                {
                    if (action == NotifyCollectionChangedAction.Add)
                    {
                        var index = generator.IndexFromGeneratorPosition(args.Position);
                        // ItemContainerGenerator is infested with bugs. One of which is that as items are added to the end of a collection, the index from IndexFromGeneratorPosition will usually be wrong.
                        if (args.Position.Offset == 1)
                        {
                            index = items.Count - 1;
                        }
                        var newItems = new VirtualItemsList(items, index, args.ItemCount);

                        if (!IsVirtualizing)
                        {
                            for (int i = index; i < index + args.ItemCount; i++)
                            {
                                RealizeItem(i);
                            }
                        }

                        OnItemsChanged(items, new NotifyCollectionChangedEventArgs(action, newItems, index));
                    }
                    else if (action == NotifyCollectionChangedAction.Remove)
                    {
                        var oldIndex = generator.IndexFromGeneratorPosition(args.Position);
                        var oldItems = new ArrayList(args.ItemCount);

                        // Since we can't actually get the old items directly, and sometimes we can't even get the old index from the generator, we'll get as many as we can from the visuals.
                        for (int i = 0; i < args.ItemUICount; i++)
                        {
                            var element = InternalChildren[args.Position.Index + i];
                            oldItems.Add(ItemFromContainer(element));
                            if (oldIndex == -1)
                            {
                                oldIndex = (int)element.ReadLocalValue(IndexForItemContainerProperty);
                            }
                            element.ClearValue(IndexForItemContainerProperty);
                        }

                        // Unfortunately ItemContainerGenerator always expects us to remove the child, even if we didn't want to.
                        if (args.ItemUICount > 0)
                        {
                            RemoveInternalChildRange(args.Position.Index, args.ItemUICount);
                        }

                        OnItemsChanged(items, new NotifyCollectionChangedEventArgs(action, oldItems, oldIndex));
                    }
                    else if (action == NotifyCollectionChangedAction.Move)
                    {
                        var oldIndex   = -1;
                        var index      = generator.IndexFromGeneratorPosition(args.Position);
                        var movedItems = new VirtualItemsList(items, index, args.ItemCount);

                        var count = args.ItemUICount;
                        if (count > 0)
                        {
                            var elements = new UIElement[count];
                            for (var i = 0; i < count; i++)
                            {
                                elements[i] = InternalChildren[args.OldPosition.Index + i];
                                if (oldIndex == -1)
                                {
                                    oldIndex = (int)elements[i].ReadLocalValue(IndexForItemContainerProperty);
                                }
                            }
                            RemoveInternalChildRange(args.OldPosition.Index + Math.Min(args.OldPosition.Offset, 1), count);
                            for (var i = 0; i < count; i++)
                            {
                                InsertInternalChild(args.Position.Index + i, elements[i]);
                            }
                        }

                        OnItemsChanged(items, new NotifyCollectionChangedEventArgs(action, movedItems, index, oldIndex));
                    }
                    else if (action == NotifyCollectionChangedAction.Replace)
                    {
                        var index    = generator.IndexFromGeneratorPosition(args.Position);
                        var newItems = new VirtualItemsList(items, index, args.ItemCount);
                        // Todo: Actually get the old items.  ItemContainerGenerator doesn't make this easy.
                        var oldItems = new VirtualItemsList(null, index, args.ItemCount);

                        OnItemsChanged(items, new NotifyCollectionChangedEventArgs(action, newItems, oldItems, index));
                    }
                }
            }

            base.OnItemsChanged(sender, args);

            InvalidateReality();
        }
Beispiel #3
0
        protected sealed override void OnItemsChanged(object sender, ItemsChangedEventArgs args)
        {
            if (args == null)
            {
                throw new ArgumentNullException("args");
            }
            ItemCollection itemCollection        = ItemsOwner?.Items;
            NotifyCollectionChangedAction action = args.Action;

            if (action == NotifyCollectionChangedAction.Reset)
            {
                OnItemsChanged(itemCollection, new NotifyCollectionChangedEventArgs(action));
            }
            else if (itemCollection != null)
            {
                IItemContainerGenerator itemContainerGenerator = sender as IItemContainerGenerator;
                if (itemContainerGenerator != null)
                {
                    switch (action)
                    {
                    case NotifyCollectionChangedAction.Add:
                    {
                        int num4 = itemContainerGenerator.IndexFromGeneratorPosition(args.Position);
                        if (args.Position.Offset == 1)
                        {
                            num4 = itemCollection.Count - 1;
                        }
                        VirtualItemsList changedItems2 = new VirtualItemsList(itemCollection, num4, args.ItemCount);
                        if (!IsVirtualizing)
                        {
                            for (int k = num4; k < num4 + args.ItemCount; k++)
                            {
                                RealizeItem(k);
                            }
                        }
                        OnItemsChanged(itemCollection, new NotifyCollectionChangedEventArgs(action, changedItems2, num4));
                        break;
                    }

                    case NotifyCollectionChangedAction.Remove:
                    {
                        int       num5      = itemContainerGenerator.IndexFromGeneratorPosition(args.Position);
                        ArrayList arrayList = new ArrayList(args.ItemCount);
                        for (int l = 0; l < args.ItemUICount; l++)
                        {
                            UIElement uIElement = base.InternalChildren[args.Position.Index + l];
                            arrayList.Add(ItemFromContainer(uIElement));
                            if (num5 == -1)
                            {
                                num5 = (int)uIElement.ReadLocalValue(IndexForItemContainerProperty);
                            }
                            uIElement.ClearValue(IndexForItemContainerProperty);
                        }
                        if (args.ItemUICount > 0)
                        {
                            RemoveInternalChildRange(args.Position.Index, args.ItemUICount);
                        }
                        OnItemsChanged(itemCollection, new NotifyCollectionChangedEventArgs(action, arrayList, num5));
                        break;
                    }

                    case NotifyCollectionChangedAction.Move:
                    {
                        int num2 = -1;
                        int num3 = itemContainerGenerator.IndexFromGeneratorPosition(args.Position);
                        VirtualItemsList changedItems = new VirtualItemsList(itemCollection, num3, args.ItemCount);
                        int itemUICount = args.ItemUICount;
                        if (itemUICount > 0)
                        {
                            UIElement[] array = new UIElement[itemUICount];
                            for (int i = 0; i < itemUICount; i++)
                            {
                                array[i] = base.InternalChildren[args.OldPosition.Index + i];
                                if (num2 == -1)
                                {
                                    num2 = (int)array[i].ReadLocalValue(IndexForItemContainerProperty);
                                }
                            }
                            RemoveInternalChildRange(args.OldPosition.Index + Math.Min(args.OldPosition.Offset, 1), itemUICount);
                            for (int j = 0; j < itemUICount; j++)
                            {
                                InsertInternalChild(args.Position.Index + j, array[j]);
                            }
                        }
                        OnItemsChanged(itemCollection, new NotifyCollectionChangedEventArgs(action, changedItems, num3, num2));
                        break;
                    }

                    case NotifyCollectionChangedAction.Replace:
                    {
                        int num = itemContainerGenerator.IndexFromGeneratorPosition(args.Position);
                        VirtualItemsList newItems = new VirtualItemsList(itemCollection, num, args.ItemCount);
                        VirtualItemsList oldItems = new VirtualItemsList(null, num, args.ItemCount);
                        OnItemsChanged(itemCollection, new NotifyCollectionChangedEventArgs(action, newItems, oldItems, num));
                        break;
                    }
                    }
                }
            }
            base.OnItemsChanged(sender, args);
            InvalidateReality();
        }