internal void RemoveAllInternal(bool saveRecycleQueue)
        {
            // Take _itemMap offline, to protect against reentrancy (bug 1285179)
            ItemBlock itemMap = _itemMap;
            _itemMap = null;

            try
            {
                // de-initialize the containers that are being removed
                if (itemMap != null)
                {
                    for (ItemBlock block = itemMap.Next;  block != itemMap;  block = block.Next)
                    {
                        RealizedItemBlock rib = block as RealizedItemBlock;
                        if (rib != null)
                        {
                            for (int offset = 0; offset < rib.ContainerCount; ++offset)
                            {
                                UnlinkContainerFromItem(rib.ContainerAt(offset), rib.ItemAt(offset));
                            }
                        }
                    }
                }
            }
            finally
            {
                PrepareGrouping();

                // re-initialize the data structure
                _itemMap = new ItemBlock();
                _itemMap.Prev = _itemMap.Next = _itemMap;

                UnrealizedItemBlock uib = new UnrealizedItemBlock();
                uib.InsertAfter(_itemMap);
                uib.ItemCount = ItemsInternal.Count;

                if (!saveRecycleQueue)
                {
                    ResetRecyclableContainers();
                }

                SetAlternationCount();

                // tell generators what happened
                if (MapChanged != null)
                {
                    MapChanged(null, -1, 0, uib, 0, 0);
                }
            }
        }
        // "Realize" the item in a block at the given offset, to be
        // the given item with corresponding container.  This means updating
        // the item map data structure so that the item belongs to a Realized block.
        // It also requires updating the state of every generator to track the
        // changes we make here.
        void Realize(UnrealizedItemBlock block, int offset, object item, DependencyObject container)
        {
            RealizedItemBlock prevR, nextR;

            RealizedItemBlock newBlock; // new location of the target item
            int newOffset;              // its offset within the new block
            int deltaCount;             // diff between cumulative item count of block and newBlock

            // if we're realizing the leftmost item and there's room in the
            // previous block, move it there
            if (offset == 0 &&
                (prevR = block.Prev as RealizedItemBlock) != null &&
                prevR.ItemCount < ItemBlock.BlockSize)
            {
                newBlock = prevR;
                newOffset = prevR.ItemCount;
                MoveItems(block, offset, 1, newBlock, newOffset, -prevR.ItemCount);
                MoveItems(block, 1, block.ItemCount, block, 0, +1);
            }

            // if we're realizing the rightmost item and there's room in the
            // next block, move it there
            else if (offset == block.ItemCount - 1 &&
                (nextR = block.Next as RealizedItemBlock) != null &&
                nextR.ItemCount < ItemBlock.BlockSize)
            {
                newBlock = nextR;
                newOffset = 0;
                MoveItems(newBlock, 0, newBlock.ItemCount, newBlock, 1, -1);
                MoveItems(block, offset, 1, newBlock, newOffset, offset);
            }

            // otherwise we need a new block for the target item
            else
            {
                newBlock = new RealizedItemBlock();
                newOffset = 0;
                deltaCount = offset;

                // if target is leftmost item, insert it before remaining items
                if (offset == 0)
                {
                    newBlock.InsertBefore(block);
                    MoveItems(block, offset, 1, newBlock, newOffset, 0);
                    MoveItems(block, 1, block.ItemCount, block, 0, +1);
                }

                // if target is rightmost item, insert it after remaining items
                else if (offset == block.ItemCount - 1)
                {
                    newBlock.InsertAfter(block);
                    MoveItems(block, offset, 1, newBlock, newOffset, offset);
                }

                // otherwise split the block into two, with the target in the middle
                else
                {
                    UnrealizedItemBlock newUBlock = new UnrealizedItemBlock();
                    newUBlock.InsertAfter(block);
                    newBlock.InsertAfter(block);
                    MoveItems(block, offset+1, block.ItemCount-offset-1, newUBlock, 0, offset+1);
                    MoveItems(block, offset, 1, newBlock, 0, offset);
                }
            }

            RemoveAndCoalesceBlocksIfNeeded(block);

            // add the new target to the map
            newBlock.RealizeItem(newOffset, item, container);
        }