lepoco/wpfui · error · ArgumentOutOfRangeException

The argument {nameof(index)} must be >= 0 and < the number o

Error message

The argument {nameof(index)} must be >= 0 and < the number of items.

What it means

VirtualizingWrapPanel.BringIndexIntoView is the WPF virtualisation contract method called by the framework (and ItemsControl bring-into-view logic) to scroll a given item index into view. It validates that index is within [0, Items.Count) and throws ArgumentOutOfRangeException otherwise. This guards against the panel trying to compute an offset for a row that does not exist.

Source

Thrown at src/Wpf.Ui/Controls/VirtualizingWrapPanel/VirtualizingWrapPanel.cs:495

    }

    /// <summary>
    /// Gets item row index.
    /// </summary>
    private int GetRowIndex(double location)
    {
        var calculatedRowIndex = (int)Math.Floor(location / GetHeight(ChildSize));
        var maxRowIndex = (int)Math.Ceiling((double)Items.Count / (double)ItemsPerRowCount);

        return Math.Max(Math.Min(calculatedRowIndex, maxRowIndex), 0);
    }

    /// <inheritdoc />
    protected override void BringIndexIntoView(int index)
    {
        if (index < 0 || index >= Items.Count)
        {
            throw new ArgumentOutOfRangeException(
                nameof(index),
                $"The argument {nameof(index)} must be >= 0 and < the number of items."
            );
        }

        if (ItemsPerRowCount == 0)
        {
            throw new InvalidOperationException();
        }

        var offset = (index / ItemsPerRowCount) * GetHeight(ChildSize);

        if (Orientation == Orientation.Horizontal)
        {
            SetHorizontalOffset(offset);
        }
        else
        {

View on GitHub (pinned to ffebacd610)

Solutions

  1. Bounds-check against the live collection count before calling BringIndexIntoView.
  2. Re-resolve the index from the item (e.g. via IndexOf) right before scrolling, after any collection reset.
  3. Avoid scrolling to an index during collection-change notifications; defer to the dispatcher.

Example fix

// before
panel.BringIndexIntoView(selectedIndex);

// after
if (selectedIndex >= 0 && selectedIndex < items.Count)
{
    panel.BringIndexIntoView(selectedIndex);
}
Defensive patterns

Strategy: validation

Validate before calling

if (index < 0 || index >= items.Count)
{
    throw new ArgumentOutOfRangeException(nameof(index));
}
panel.BringIndexIntoView(index);

Type guard

static bool IsInViewRange(int index, int count) => index >= 0 && index < count;

Try / catch

try { panel.BringIndexIntoView(index); }
catch (ArgumentOutOfRangeException ex) when (ex.ParamName == "index")
{
    _logger.LogDebug(ex, "Stale index {Index} no longer in range.", index);
}

Prevention

When it happens

Trigger: The framework or user code calls BringIndexIntoView with an index that is negative or >= the current Items.Count - e.g. after the source collection changed but before the panel's Items was synchronised, or a stale index retained from a previous larger collection.

Common situations: Collection is replaced/reset between selecting an item and scrolling it into view; bound source filtered down so a previously valid index is now out of range; off-by-one when computing the last index; calling BringIndexIntoView on an empty list.

Related errors


AI-assisted analysis of lepoco/wpfui@ffebacd610 (2026-08-13). Data as JSON: /api/errors/b4e4b2b5954a5a2c. Report an issue: GitHub.