dotnet/maui · error · ArgumentException

Renderer's container element must be a Panel

Error message

Renderer's container element must be a Panel

What it means

VisualElementPackager constructor throws ArgumentException when renderer.ContainerElement is not a WinUI Panel. The packager adds child elements to the container's Children collection, which only exists on Panel-derived types (Grid, StackPanel, Canvas, etc.). Non-Panel containers like ContentControl or Border lack the Children collection.

Source

Thrown at src/Compatibility/Core/src/Windows/VisualElementPackager.cs:30

		readonly int _columnSpan;

		readonly Panel _panel;
		readonly IVisualElementRenderer _renderer;
		readonly int _row;
		readonly int _rowSpan;
		bool _disposed;
		bool _isLoaded;

		public VisualElementPackager(IVisualElementRenderer renderer)
		{
			if (renderer == null)
				throw new ArgumentNullException("renderer");

			_renderer = renderer;

			_panel = renderer.ContainerElement as Panel;
			if (_panel == null)
				throw new ArgumentException("Renderer's container element must be a Panel");
		}

		public VisualElementPackager(IVisualElementRenderer renderer, int row = 0, int rowSpan = 0, int column = 0, int columnSpan = 0) : this(renderer)
		{
			_row = row;
			_rowSpan = rowSpan;
			_column = column;
			_columnSpan = columnSpan;
		}

		IElementController ElementController => _renderer.Element as IElementController;

		public void Dispose()
		{
			Dispose(true);
			GC.SuppressFinalize(this);
		}

View on GitHub (pinned to f377ff1c5e)

Solutions

  1. Override ContainerElement in the custom renderer to return a Panel-derived type (Grid is the most common choice)
  2. Use a base renderer class (like ViewRenderer<TElement,TNative>) that already provides a Panel container
  3. If the native control must be non-Panel, wrap it in a Grid and return the Grid as ContainerElement

Example fix

// before
public class MyRenderer : VisualElementRenderer<MyView, Border>
{
    // ContainerElement is Border — VisualElementPackager throws
}

// after
public class MyRenderer : VisualElementRenderer<MyView>
{
    Grid _panel;
    public override UIElement ContainerElement => _panel ?? (_panel = new Grid());
    // VisualElementPackager now works — _panel is a Panel
Defensive patterns

Strategy: type-guard

Validate before calling

// Before constructing VisualElementPackager, verify ContainerElement is a Panel
if (renderer.ContainerElement is not Panel)
    throw new ArgumentException($"ContainerElement must be a Panel, got {renderer.ContainerElement?.GetType().Name}");
var packager = new VisualElementPackager(renderer);

Type guard

static bool HasPanelContainer(IVisualElementRenderer renderer)
{
    return renderer?.ContainerElement is Panel;
}

Prevention

When it happens

Trigger: Constructing a VisualElementPackager with a renderer whose ContainerElement is a non-Panel type — e.g. a custom renderer that wraps its content in a Border, ContentControl, or UserControl rather than a Grid.

Common situations: Custom renderer overriding ContainerElement to return a non-Panel element; renderer that uses ContentControl.Content instead of Panel.Children for layout; incorrect base class choice for custom renderer.

Related errors


AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13). Data as JSON: /api/errors/94097481db2b6605. Report an issue: GitHub.