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
- Override ContainerElement in the custom renderer to return a Panel-derived type (Grid is the most common choice)
- Use a base renderer class (like ViewRenderer<TElement,TNative>) that already provides a Panel container
- 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
- Override ContainerElement to return a Grid or other Panel-derived type in custom renderers
- Use ViewRenderer<TElement,TNative> base class which provides a Panel container
- Verify ContainerElement type in renderer unit tests
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
- Element must be a TabbedPage
- renderer
- Could not find or create a renderer for {visualElement}
- self
- Cannot assign a native control without an Element; Renderer
AI-assisted analysis of dotnet/maui@f377ff1c5e (2026-08-13).
Data as JSON: /api/errors/94097481db2b6605.
Report an issue: GitHub.