VirtualizingStackPanel has two modes. One is called ScrollToContent and in such mode the VirtualizingStackPanel uses indexes of items. As example visible are 10 items and you have an amount of 1000 items therefore the ScrollBar will be displayed small.
The second mode is called ScrollToPixels and in this mode the VirtualizingStackPanel manages a list of which items are virtualized and which are realized. If an item is not realized yet the VirtualizingStackPanel uses its MinHeight value which if none set by user 16 pixels for microsoft. As example visible are 10 items and each item has height of 20 pixels. That would be 200 pixels for viewport height but you have a total amout of 1000 items so the extent will be then 200 + (1000 - 10 ) * 16 = 16040 pixels. The ScrollBar will also appear small and in proper propotion.
In the end VirtualizingStackPanel is a complex thing and it works great mostly. It also allows virtualization vertically and horizontally which is awesome. If you wish to write your own VirtualizingStackPanel I would suggest you to stop reinventing the wheel. You will end up doing the same in code as microsoft guys did so why waisting time when somebody else already developed the VirtualizingStackPanel :)
I reflectored VirtualizingStackPanel with RedGate tool. Take a look at this:
private Size ContainerSizeForItem(ItemsControl itemsControl, object item, int index, out UIElement container)
{
Size containerSize;
container = index >= 0 ? ((ItemContainerGenerator)Generator).ContainerFromIndex(index) as UIElement : null;
if (container != null)
{
containerSize = container.DesiredSize;
}
else
{
// It's virtualized; grab the height off the item if available.
object value = itemsControl.ReadItemValue(item, _desiredSizeStorageIndex);
if (value != null)
{
containerSize = (Size)value;
}
else
{
//
// No stored container height; simply guess.
//
containerSize = new Size();
if (Orientation == Orientation.Horizontal)
{
containerSize.Width = ContainerStackingSizeEstimate(itemsControl, /*isHorizontal = */ true);
containerSize.Height = DesiredSize.Height;
}
else
{
containerSize.Height = ContainerStackingSizeEstimate(itemsControl, /*isHorizontal = */ false);
containerSize.Width = DesiredSize.Width;
}
}
}
return containerSize;
}
private double ContainerStackingSizeEstimate(IProvideStackingSize estimate, bool isHorizontal)
{
double stackingSize = 0d;
if (estimate != null)
{
stackingSize = estimate.EstimatedContainerSize(isHorizontal);
}
if (stackingSize <= 0d || DoubleUtil.IsNaN(stackingSize))
{
stackingSize = ScrollViewer._scrollLineDelta;
}
return stackingSize;
}
If you reflect ScrollViewer you will find this:
internal const double _scrollLineDelta = 16.0; // Default physical amount to scroll with one Up/Down
As you can see the size is guessed when container not avaiable which means its set to 16.0 pixel which is default for microsoft.
Btw pixel scrolling was there in wpf since begin also since .Net 3.5 just see TreeView for example. :) :)