dotnet/wpf · error · InvalidOperationException

SR.AdornedElementPlaceholderMustBeInTemplate

Error message

SR.AdornedElementPlaceholderMustBeInTemplate

What it means

AdornedElementPlaceholder is a control that only makes sense as part of a Validation error template; OnInitialized throws InvalidOperationException when the control is created with no TemplatedParent (i.e. instantiated directly rather than inside a ControlTemplate).

Solutions

  1. Use AdornedElementPlaceholder only inside a ControlTemplate (typically a Validation ErrorTemplate)
  2. Set Validation.ErrorTemplate on the bound control instead of hosting the placeholder directly
  3. If you need a standalone adornment, use Adorner/AdornerLayer APIs directly

Example fix

<!-- before -->
<StackPanel>
  <AdornedElementPlaceholder/>
</StackPanel>
<!-- after -->
<ControlTemplate x:Key="errorTemplate">
  <AdornedElementPlaceholder Name="placeholder"/>
</ControlTemplate>
<TextBox Validation.ErrorTemplate="{StaticResource errorTemplate}" .../>
Defensive patterns

Strategy: validation

Validate before calling

if (placeholder.TemplatedParent == null)
    throw new InvalidOperationException("AdornedElementPlaceholder must be inside a ControlTemplate.");

Try / catch

try
{
    InitializePlaceholder();
}
catch (InvalidOperationException ex) when (ex.Message.Contains("template"))
{
    // restructure XAML to place the control in a template
}

Prevention

When it happens

Trigger: Placing <AdornedElementPlaceholder/> directly in page/window XAML instead of inside a ControlTemplate; creating an AdornedElementPlaceholder instance in code (new AdornedElementPlaceholder()) outside any template.

Common situations: Developer tries to use the placeholder as a standalone decorative element; copying the ErrorTemplate XAML fragment out of its template context; testing the control in isolation.

Understand the failure class

Background: "Invalid state transition" errors: "status must be X, actually Y", "already rejected/charging/uninstalled", "cannot ... while running" — what they mean when a library rejects your call — this error's family across 31 libraries.

Related errors


AI-assisted analysis of dotnet/wpf@81131a70a4 (2026-09-14). Data as JSON: /api/errors/027d0daa7cd04305. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/System/Windows/Controls/AdornedElementPlaceholder.cs:165

        /// <summary>
        /// Returns enumerator to logical children.
        /// </summary>
        protected internal override IEnumerator LogicalChildren
        {
            get
            {
                // Could optimize this code by returning EmptyEnumerator.Instance if _child == null.
                return new SingleChildEnumerator(_child);
            }
        }

        /// <summary>
        ///     This virtual method in called when IsInitialized is set to true and it raises an Initialized event
        /// </summary>
        protected override void OnInitialized(EventArgs e)
        {
            if (TemplatedParent == null)
                throw new InvalidOperationException(SR.AdornedElementPlaceholderMustBeInTemplate);

            base.OnInitialized(e);
        }


        /// <summary>
        ///     AdornedElementPlaceholder measure behavior is to measure
        ///     only the first visual child.  Note that the return value
        ///     of Measure on this child is ignored as the purpose of this
        ///     class is to match the size of the element for which this
        ///     is a placeholder.
        /// </summary>
        /// <param name="constraint">The measurement constraints.</param>
        /// <returns>The desired size of the control.</returns>
        protected override Size MeasureOverride(Size constraint)
        {
            if (TemplatedParent == null)
                throw new InvalidOperationException(SR.AdornedElementPlaceholderMustBeInTemplate);

View on GitHub (pinned to 81131a70a4)