     {
         return dataProvider ? dataProvider.length : 0;
     }
+
+    private var virtualLayoutOffset:int = 0;
+    private var virtualLayoutUnderway:Boolean = false;
+     
+    /**
+     *  @private
+     *  Update virtualLayoutOffset and clear the virtualLayoutUnderway flag.
+     */
+    override public function beginVirtualLayout(startIndex:int):void
+    {
+        virtualLayoutOffset = startIndex;
+        virtualLayoutUnderway = true;
+    }
+    
+    /**
+     *  @private
+     *  Discard the ItemRenderers that aren't needed anymore, i.e. the ones
+     *  outside the logical range startIndex to endIndex.
+     * 
+     *  Clear the virtualLayoutUnderway flag.
+     */
+    override public function endVirtualLayout(startIndex:int, endIndex:int):void
+    {
+        // At this point, insertion of new IRs has pushed all of the unneeded IRs
+        // past endIndex-startIndex.  Remove them without invalidating this DataGroup's
+        // size or display list.
+        for(var i:int = super.numChildren - 1; i > (endIndex - startIndex); i--)
+        {
+            var itemRenderer:DisplayObject = super.getChildAt(i);
+            unregisterRenderer(i, IVisualElement(itemRenderer));
+            super.removeChildAt(i);
+        }        
+        virtualLayoutUnderway = false;
+    }
+    
+    /**
+     *  @private
+     */
+    override public function invalidateSize():void
+    {
+        if (!virtualLayoutUnderway)
+            super.invalidateSize();
+    }
     
     /**
      *  @private
      */
     override public function getLayoutElementAt(index:int):ILayoutElement
     {
-        var myItemRenderer:Object = mx_internal::getRendererForItemAt(index);
-
-        return LayoutElementFactory.getLayoutElementFor(myItemRenderer);
-    }
-    
+        var itemRendererIndex:int = index - virtualLayoutOffset;
+        var itemRenderer:Object = mx_internal::getRendererForItemAt(itemRendererIndex);
+
+        if (layout && layout.virtualLayout)
+        {
+            // Note: the code below does most of the same work as itemAdded()
+            var item:Object = dataProvider.getItemAt(index);
+            var createdIR:Boolean = false;
+            
+            if (!itemRenderer)
+            {
+                itemRenderer = createRendererForItem(item);
+                createdIR = true;
+            }
+
+            if (itemRenderer.parent != this)
+                addItemRendererToDisplayList(DisplayObject(itemRenderer), itemRendererIndex);
+            else
+                super.setChildIndex(DisplayObject(itemRenderer), itemRendererIndex);
+            
+            if (createdIR)
+            {
+                if (itemRenderer is IInvalidating)
+                    IInvalidating(itemRenderer).validateNow();
+                // TBD sync with itemAdded
+                dispatchEvent(new ItemExistenceChangedEvent(ItemExistenceChangedEvent.ITEM_ADD, false, false, item));
+            }
+        }
+
+        return LayoutElementFactory.getLayoutElementFor(itemRenderer);
+    }
+
     /**
      *  @private
      */

        {
        	manageDisplayObjectLayers();
        }
    }
    
    private function manageDisplayObjectLayers():void

    
    private var itemRendererRegistry:Array = [];
    
    //--------------------------------------------------------------------------
    //
    //  Properties
    //
    //--------------------------------------------------------------------------
    
    //----------------------------------
    //  typicalItem
    //----------------------------------

    private var _typicalItem:Object = null;
    private var typicalItemChanged:Boolean = false;
    private var typicalLayoutElement:ILayoutElement = null;

    /**
     *  Layouts use the preferred size of the corresponding ILayoutElement 
     *  when fixed row/column sizes are requested but a specific 
     *  rowHeight or columnWidth isn't provided.
     * 
     *  Similarly virtual layouts use this item to define the size 
     *  of layout elements that have not been scrolled into view.
     *
     *  Setting this property sets the typicalLayoutElement property
     *  of the layout.
     * 
     *  @default null
     */
    public function get typicalItem():Object
    {
        return _typicalItem;
    }

    /**
     *  @private
     */
    public function set typicalItem(value:Object):void
    {
        if (_typicalItem == value)
            return;
        _typicalItem = value;
        typicalItemChanged = true;
        invalidateProperties();
    }
    
    private function initializeTypicalItem():void
    {
        var itemRenderer:DisplayObject = DisplayObject(createRendererForItem(_typicalItem));     
        super.addChild(itemRenderer)            
        if (itemRenderer is IInvalidating)
            IInvalidating(itemRenderer).validateNow();
        typicalLayoutElement = LayoutElementFactory.getLayoutElementFor(itemRenderer);
        if (layout)
            layout.typicalLayoutElement = typicalLayoutElement;    
        super.removeChild(itemRenderer);
    }    

    //----------------------------------
    //  layout
    //----------------------------------

    /**
     *  @private
     *  Sync the typicalLayoutElement var with this group's layout.
     */    
    override public function set layout(value:LayoutBase):void
    {
        var oldLayout:LayoutBase = layout;
        if (value == oldLayout)
            return; 

        super.layout = value;    
        if (oldLayout)
            oldLayout.typicalLayoutElement = null;
        if (value)
            value.typicalLayoutElement = typicalLayoutElement;
    } 
    
    //----------------------------------
    //  itemRenderer
    //----------------------------------
