dotnet/wpf · error · InvalidOperationException

SR.Format(SR.ComponentAlreadyInPresentationContext…

Error message

SR.Format(SR.ComponentAlreadyInPresentationContext, adorner.AnnotationComponent)

What it means

Thrown by the AdornerPresentationContext constructor when the supplied AnnotationAdorner's AnnotationComponent is already attached to another presentation context. The WPF Annotations framework requires each annotation component to live in exactly one presentation context so its visual/adorner bookkeeping stays consistent. Attempting to reuse a component that is still registered elsewhere violates that invariant, so an InvalidOperationException is raised.

Solutions

  1. Remove the component from its current presentation context (call RemoveFromHost / context.RemoveFromHost) before constructing a new AdornerPresentationContext for it.
  2. Create a fresh AnnotationAdorner/AnnotationComponent instance for each context instead of reusing one.
  3. Check adorner.AnnotationComponent.PresentationContext != null before constructing and branch to an update path instead of re-adding.
  4. If the old host element is gone, ensure the context's cleanup ran so PresentationContext is reset to null.

Example fix

// before
var context = new AdornerPresentationContext(adornerLayer, adorner); // throws if reused
// after
if (adorner.AnnotationComponent.PresentationContext != null)
    adorner.AnnotationComponent.PresentationContext.RemoveFromHost(adorner.AnnotationComponent);
var context = new AdornerPresentationContext(adornerLayer, adorner);
Defensive patterns

Strategy: validation

Validate before calling

if (adorner?.AnnotationComponent == null) throw new ArgumentNullException(nameof(adorner));
if (adorner.AnnotationComponent.PresentationContext != null)
    adorner.AnnotationComponent.PresentationContext.RemoveFromHost(adorner.AnnotationComponent);

Type guard

bool IsAttachable(AnnotationAdorner a) => a?.AnnotationComponent != null && a.AnnotationComponent.PresentationContext == null;

Try / catch

try { var ctx = new AdornerPresentationContext(layer, adorner); }
catch (InvalidOperationException) { /* component already hosted; reuse or remove first */ }

Prevention

When it happens

Trigger: Calling the AdornerPresentationContext(adornerLayer, adorner) constructor with an AnnotationAdorner whose AnnotationComponent.PresentationContext is non-null — i.e. the component was previously added to this or another context and not removed.

Common situations: Reusing a single AnnotationAdorner/AnnotationComponent instance across multiple annotated elements or multiple AdornerLayer/DocumentViewerHost instances; forgetting to call RemoveFromHost before re-attaching; caching annotation components in application state and re-adding them after a control is re-hosted.

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/be95efb62f1f9040. Report an issue: GitHub.

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Annotations/Component/AdornerPresentationContext.cs:46

        #region Constructors

        /// <summary>
        /// Create an initialized instance of an AdornerPresentationContext. Set the presentation context of the 
        /// component wrapped in the adorner
        /// </summary>
        /// <param name="adornerLayer">AdornerLayer this presentation context is on, must not be null</param>
        /// <param name="adorner">AnnotationAdorner that wraps the annotation component.  Will be null in case of creating enclosing context</param>
        private AdornerPresentationContext(AdornerLayer adornerLayer, AnnotationAdorner adorner)
        {
            ArgumentNullException.ThrowIfNull(adornerLayer);

            _adornerLayer = adornerLayer;
            if (adorner != null)
            {
                if (adorner.AnnotationComponent == null)
                    throw new ArgumentNullException("annotation component");
                if (adorner.AnnotationComponent.PresentationContext != null)
                    throw new InvalidOperationException(SR.Format(SR.ComponentAlreadyInPresentationContext, adorner.AnnotationComponent));
                _annotationAdorner = adorner;
            }
        }

        #endregion Constructors

        #region Static Methods

        /// <summary>
        /// Host a component in an adorner layer.
        /// Wrap the component in an annotation adorner, add that to the adorner layer, create and set presentation context and invalidate to pick up styles.
        /// Note, this is called from two places: (1) component manager to host choosen annotation component, and (2) presentation context when component
        /// adds additional IAnnotationComponent.
        /// </summary>
        /// <param name="adornerLayer">Adorner layer the component is hosted in</param>
        /// <param name="component">Component that is being hosted</param>
        /// <param name="annotatedElement">element being annotated</param>
        /// <param name="reorder">if true - put the component on top and calculate its z-order</param>

View on GitHub (pinned to 81131a70a4)