lepoco/wpfui · error · ArgumentOutOfRangeException

IconElement should have only 1 child

Error message

IconElement should have only 1 child

What it means

Thrown by IconElement.GetVisualChild when WPF (or a derived class) requests a visual child at an index other than 0. IconElement is contractually single-child: it hosts exactly one Grid (_layoutRoot). Requesting index 1+ violates the VisualChildrenCount=1 contract and indicates either a subclass that added visuals without overriding the count, or a framework caller bug.

Source

Thrown at src/Wpf.Ui/Controls/IconElement/IconElement.cs:73

    private void EnsureLayoutRoot()
    {
        if (_layoutRoot != null)
        {
            return;
        }

        _layoutRoot = new Grid { Background = Brushes.Transparent, SnapsToDevicePixels = true };

        _ = _layoutRoot.Children.Add(InitializeChildren());

        AddVisualChild(_layoutRoot);
    }

    protected override Visual GetVisualChild(int index)
    {
        if (index != 0)
        {
            throw new ArgumentOutOfRangeException(nameof(index), "IconElement should have only 1 child");
        }

        EnsureLayoutRoot();
        return _layoutRoot!;
    }

    protected override Size MeasureOverride(Size availableSize)
    {
        EnsureLayoutRoot();

        _layoutRoot!.Measure(availableSize);
        return _layoutRoot.DesiredSize;
    }

    protected override Size ArrangeOverride(Size finalSize)
    {
        EnsureLayoutRoot();

View on GitHub (pinned to ffebacd610)

Solutions

  1. If subclassing IconElement, keep VisualChildrenCount at 1 or override GetVisualChild to return the correct child for each index.
  2. Do not call AddVisualChild on an IconElement subclass without also overriding the count and GetVisualChild.
  3. If you are a consumer (not a subclasser), report the issue — this path should be unreachable through normal API use.
  4. Verify no adorner layer is injecting children into an icon element.

Example fix

// before (broken subclass)
public class MyIcon : IconElement {
    private readonly Visual _extra;
    protected override int VisualChildrenCount => 2; // GetVisualChild(1) throws
}

// after
protected override int VisualChildrenCount => 1;
protected override Visual GetVisualChild(int index) =>
    index == 0 ? _layoutRoot! : throw new ArgumentOutOfRangeException(nameof(index));
Defensive patterns

Strategy: validation

Validate before calling

// Framework invariant — not user-callable. If subclassing IconElement:
protected override int VisualChildrenCount => 1;
protected override Visual GetVisualChild(int index) =>
    index == 0 ? base.GetVisualChild(0)
               : throw new ArgumentOutOfRangeException(nameof(index));

Prevention

When it happens

Trigger: A subclass of IconElement overrides VisualChildrenCount or adds visual children without overriding GetVisualChild; WPF measure/arrange or an ancestor panel calls GetVisualChild with an out-of-range index because the reported count was inflated.

Common situations: Custom IconElement subclass that adds extra children; an adorner or decorator mishandling the child count of an IconElement descendant; very rarely a WPF layout bug interacting with custom icon controls.

Related errors


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