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
- Make the custom annotation component derive from a UIElement-based class before wrapping it in AnnotationAdorner.
- Validate component is UIElement before constructing the adorner and fail fast with a clear message.
- Use one of the framework-provided components (e.g. TextHighlightComponent) which are UIElements.
- 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
- Derive custom IAnnotationComponent implementations from UIElement-based classes
- Assert UIElement-ness at component construction time, not adorner time
- Prefer framework-provided annotation components when possible
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
- SR.AudioVideo_InvalidDependencyObject
- SR.Format(SR.BadFixedTextPosition, "position")
- SR.Format(SR.CannotConvertType, key.GetType(), "int")
- SR.Format(SR.CannotConvertType, typeof(CharacterMetrics)…
- SR.Format(SR.IncorrectLocatorPartType, " : ")
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)