dotnet/wpf · error · ArgumentException

SR.AnnotationAdorner_NotUIElement

Error message

SR.AnnotationAdorner_NotUIElement

What it means

The AnnotationAdorner constructor wraps an annotation component as its visual child and therefore requires it to be a UIElement. When the passed IAnnotationComponent is not a UIElement, an ArgumentException with SR.AnnotationAdorner_NotUIElement is thrown. Annotation adorners are Visual-layer wrappers, so only visual elements can be hosted.

Solutions

  1. Make the custom annotation component derive from a UIElement-based class before wrapping it in AnnotationAdorner.
  2. Validate component is UIElement before constructing the adorner and fail fast with a clear message.
  3. Use one of the framework-provided components (e.g. TextHighlightComponent) which are UIElements.
  4. If the component genuinely cannot be visual, wrap its visuals in a UIElement host rather than the component itself.

Example fix

// before
IAnnotationComponent comp = new MyNonVisualComponent();
var adorner = new AnnotationAdorner(comp); // ArgumentException
// after
if (comp is not UIElement)
    throw new ArgumentException("Annotation component must be a UIElement");
var adorner = new AnnotationAdorner(comp);
Defensive patterns

Strategy: validation

Validate before calling

if (component is not UIElement)
    throw new ArgumentException("Annotation component must be a UIElement", nameof(component));

Type guard

bool IsWrappable(IAnnotationComponent c) => c is UIElement;

Try / catch

try { var adorner = new AnnotationAdorner(component); }
catch (ArgumentException) { /* component is not a UIElement */ }

Prevention

When it happens

Trigger: Calling new AnnotationAdorner(component) where component is an IAnnotationComponent implementation that does not derive from UIElement (e.g. a custom non-visual annotation component).

Common situations: Writing a custom IAnnotationComponent that implements the interface without inheriting from a UIElement base class (such as TextPanel/ContentPresenter-based components used by the built-in HighlightComponent); casting/refactoring code that changed a component's base class away from UIElement.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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

Appendix: source

Thrown at src/Microsoft.DotNet.Wpf/src/PresentationFramework/MS/Internal/Annotations/Component/AnnotationAdorner.cs:43

        /// <summary>
        /// Return an initialized annotation adorner
        /// </summary>
        /// <param name="component">The annotation component to wrap in the annotation adorner</param>
        /// <param name="annotatedElement">element being annotated</param>
        public AnnotationAdorner(IAnnotationComponent component, UIElement annotatedElement) : base(annotatedElement)
        {
            //The summary on top of the file says:-
            //The wrapped component must be at least a UIElement
            if (component is UIElement)
            {
                _annotationComponent = component;
                // wrapped annotation component is added as visual child
                this.AddVisualChild((UIElement)_annotationComponent);
            }
            else
            {
                throw new ArgumentException(SR.AnnotationAdorner_NotUIElement, nameof(component));
            }
        }

        #endregion Constructors

        #region Public Methods

        /// <summary>
        /// Forwarded to the annotation component to get desired transform relative to the annotated element
        /// </summary>
        /// <param name="transform">Transform to adorned element</param>
        /// <returns>Transform to annotation component </returns>
        public override GeneralTransform GetDesiredTransform(GeneralTransform transform)
        {
            //if the component is not visual we do not need this
            if (!(_annotationComponent is UIElement))
                return null;

View on GitHub (pinned to 81131a70a4)