/// <summary>
    /// Returns all items to the pool, re-initializes the ListScrollRect with any new values, and re-generates all visible list items.
    /// </summary>
    private void RefreshContent(int itemIndex, float contentOffset)
    {
        if (content == null)
        {
            return;
        }

        EndDrag();

        // Return all visible items to the pool
        ReturnAllToPool();

        // Clear all cached item sizes so we can start fresh
        cachedSizes.Clear();

        // Set the size of content back to its min size (ie. size with no items in it)
        content.sizeDelta = new Vector2(isVertical ? content.sizeDelta.x : PaddingLeft + PaddingRight, isVertical ? PaddingTop + PaddingBottom : content.sizeDelta.y);

        // Set the position of the content back to 0 (so its at the top)
        SetAnchoredPosition(content, 0);

        // Set the values back to default
        listInfo.Reset();

        // Get the item count from the IContentFiller
        itemCount = (dataProvider != null) ? dataProvider.Count : 0;// contentFiller.GetItemCount();

        // If there are no items then bail out here
        if (itemCount == 0)
        {
            return;
        }

        // Check the itemIndex is still in bounds
        if (itemIndex >= itemCount)
        {
            itemIndex     = itemCount - 1;
            contentOffset = 0;
        }

        // Shift the content by contentOffset, this is used so we can keep the content in the same spot after the refresh
        if (contentOffset != 0)
        {
            ShiftAnchoredPosition(content, contentOffset);
        }

        // Start generating all the items starting at index itemIndex
        GenerateListItem(itemIndex, isVertical ? -PaddingTop : PaddingLeft, false);

        // Add some height for a space if we generated items starting at an index != 0
        if (itemIndex != 0)
        {
            float width  = isVertical ? content.sizeDelta.x : content.sizeDelta.x + spacing;
            float height = isVertical ? content.sizeDelta.y + spacing : content.sizeDelta.y;

            content.sizeDelta = new Vector2(width, height);
        }

        float val1;
        float diff;

        // Get the amount of "extra" space in the scroll area that is not filled by a list item.
        if (isVertical)
        {
            val1 = content.rect.height - content.anchoredPosition.y;
            diff = ViewportSize - val1;
        }
        else
        {
            val1 = content.rect.width + content.anchoredPosition.x;
            diff = ViewportSize - val1;
        }

        // If there is "extra" space then try and fill it with items by shifting the content and checking for new items.
        if (diff > 0)
        {
            // Shift it so the content is at the end
            ShiftAnchoredPosition(content, isVertical ? -diff : diff);

            // Generate any new list items
            UpdateListItems();

            // If the contents position is less than 0 then we need to shift it back up
            if ((isVertical && content.anchoredPosition.y < 0) ||
                (!isVertical && content.anchoredPosition.x > 0))
            {
                ShiftAnchoredPosition(content, -content.anchoredPosition.y);
            }
        }

        // Save the average size of the current visible items
        listInfo.savedTotalSize = listInfo.currentTotalSize;
        listInfo.savedCount     = listInfo.currentCount;
        listInfo.usedSavedSize  = true;

        // Now we are going to calcualte the estimated size of the content using the adverage of the list items sizes we have seen so far
        int lowestIndex  = int.MaxValue;
        int highestIndex = int.MinValue;

        for (int i = 0; i < visibleObjs.Count; i++)
        {
            lowestIndex  = System.Math.Min(lowestIndex, visibleObjs[i].index);
            highestIndex = System.Math.Max(highestIndex, visibleObjs[i].index);
        }

        // This handles the edge case where items were generated before lowestIndex but were returned to the pool cause they were generated off screen
        while (cachedSizes.ContainsKey(lowestIndex - 1))
        {
            lowestIndex--;
        }

        float extraSize1 = 0;
        float extraSize2 = 0;

        // Calcuate the space that goes at the beginning
        if (lowestIndex > 0)
        {
            extraSize1 += listInfo.SavedAvgSize * lowestIndex;
        }

        // Calcuate the space that goes at the end
        if (highestIndex < itemCount - 1)
        {
            extraSize2 += listInfo.SavedAvgSize * (itemCount - highestIndex - 1);
        }

        if (extraSize1 + extraSize2 > 0)
        {
            // Resize the content
            content.sizeDelta = (isVertical ? new Vector2(content.sizeDelta.x, content.sizeDelta.y + extraSize1 + extraSize2) : new Vector2(content.sizeDelta.x + extraSize1 + extraSize2, content.sizeDelta.y));

            // If we add space at the beginning we need to shift the content so the items on the screen do not move
            if (extraSize1 > 0)
            {
                ShiftContentBy(isVertical ? extraSize1 : -extraSize1);
            }
        }


        BeginDrag();
    }