dotnet/wpf · error
VisualTree of ItemsPanelTemplate must be a single element.
Error message
VisualTree of ItemsPanelTemplate must be a single element.
What it means
After the template is applied, ItemsPresenter.OnApplyTemplate verifies the generated visual tree contains a single child that is a Panel with no children of its own. If the first visual child is not a Panel or the panel already has children, it throws InvalidOperationException because the presenter will reparent generated item containers into this panel and cannot tolerate existing content.
Solutions
- Ensure the items panel has no hardcoded children; put headers/footers outside the panel in the control template.
- Make the panel the direct (first) visual child the presenter sees; wrap the panel in a Border outside, not inside, the presenter's scope.
- Use Panel properties (Background, Padding via wrapping layout) instead of child elements to style the items area.
Example fix
<!-- before -->
<ControlTemplate TargetType="ListBox">
<StackPanel>
<TextBlock Text="Header"/>
<ItemsPresenter/>
</StackPanel>
</ControlTemplate>
<!-- wrong: children inside items panel -->
<!-- after -->
<ControlTemplate TargetType="ListBox">
<DockPanel>
<TextBlock DockPanel.Dock="Top" Text="Header"/>
<ItemsPresenter/>
</DockPanel>
</ControlTemplate> Defensive patterns
Strategy: validation
Validate before calling
var presenter = GetTemplateChild("ItemsPresenter") as ItemsPresenter;
// after ApplyTemplate:
var firstChild = VisualTreeHelper.GetChild(presenter, 0) as Panel;
if (firstChild == null || VisualTreeHelper.GetChildrenCount(firstChild) > 0)
throw new InvalidOperationException("ItemsPresenter template must yield a childless Panel as its first visual child"); Type guard
static bool IsSingleChildlessPanel(ItemsPresenter p) => VisualTreeHelper.GetChildrenCount(p) > 0 && VisualTreeHelper.GetChild(p, 0) is Panel panel && VisualTreeHelper.GetChildrenCount(panel) == 0;
Try / catch
try { presenter.ApplyTemplate(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("single element")) { /* regenerate template without panel children */ } Prevention
- Keep the items panel empty; render headers/footers outside the panel in the control template.
- Do not nest the panel inside another visual inside the ItemsPresenter subtree.
- Review custom ControlTemplates for accidental children inside the items-host panel.
When it happens
Trigger: A ControlTemplate places content inside the panel used as items host (e.g. <StackPanel><TextBlock/>...</StackPanel> inside an ItemsPresenter); the template's first visual child is not a Panel (e.g. a Border wrapping the panel) when OnApplyTemplate runs; manually calling ApplyTemplate on such a template.
Common situations: Custom control templates that add headers or footers directly inside the items panel; nesting the panel inside a Border so the first visual child is not a Panel; overriding OnApplyTemplate in derived controls that add children before base.OnApplyTemplate.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- SR.Format(SR.TemplateTargetTypeMismatch, "ItemsPresenter"…
- SR.Format(SR.VisualTreeRootIsFrameworkElement…
- ' ' is not a Visual or Visual3D.
- inverse ? SR.Visual_NotADescendant : SR.Visual_NotAnAncestor
- Page can have only Window or Frame as parent.
AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14).
Data as JSON: /api/errors/e9b26824f76bdf23.
Report an issue: GitHub.
Appendix: source
Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/ItemsPresenter.cs:46
/// <summary>
/// Called when the Template's tree is about to be generated
/// </summary>
internal override void OnPreApplyTemplate()
{
base.OnPreApplyTemplate();
AttachToOwner();
}
/// <summary>
/// This is the virtual that sub-classes must override if they wish to get
/// notified that the template tree has been created.
/// </summary>
public override void OnApplyTemplate()
{
// verify that the template produced a panel with no children
Panel panel = GetVisualChild(0) as Panel;
if (panel == null || VisualTreeHelper.GetChildrenCount(panel) > 0)
throw new InvalidOperationException(SR.ItemsPanelNotSingleNode);
OnPanelChanged(this, EventArgs.Empty);
base.OnApplyTemplate();
}
//------------------------------------------------------
//
// Protected Methods
//
//------------------------------------------------------
/// <summary>
/// Override of <seealso cref="FrameworkElement.MeasureOverride" />.
/// </summary>
/// <param name="constraint">Constraint size is an "upper limit" that the return value should not exceed.</param>
/// <returns>The ItemsPresenter's desired size.</returns>
protected override Size MeasureOverride(Size constraint)View on GitHub (pinned to 81131a70a4)