MaterialDesignInXAML/MaterialDesignInXamlToolkit · error · InvalidOperationException

This element has no adorner layer.

Error message

This element has no adorner layer.

What it means

`AdornerExtensions.AddAdorner<TAdorner>` fetches the `AdornerLayer` for a `UIElement` via `AdornerLayer.GetAdornerLayer(element)`. In WPF that returns null when the element is not yet part of a realized visual tree (e.g. no parent window/presentation source), so the extension throws `InvalidOperationException` rather than dereferencing null.

Source

Thrown at src/MaterialDesignThemes.Wpf/AdornerExtensions.cs:20

namespace MaterialDesignThemes.Wpf;

/// <summary>
/// This is a simple utility to add and remove a single adorner to an element
/// since there is no built-in way to do that in xaml.
/// <a href="https://docs.microsoft.com/en-us/dotnet/framework/wpf/controls/adorners-overview">See here</a>
/// </summary>
internal static class AdornerExtensions
{
    public static void AddAdorner<TAdorner>(this UIElement element, TAdorner adorner) where TAdorner : Adorner
    {
        if (adorner is null)
        {
            throw new ArgumentNullException(nameof(adorner));
        }

        var adornerLayer = AdornerLayer.GetAdornerLayer(element)
            ?? throw new InvalidOperationException("This element has no adorner layer.");

        adornerLayer.Add(adorner);
    }

    public static void RemoveAdorners<TAdorner>(this UIElement element) where TAdorner : Adorner
    {
        var adornerLayer = AdornerLayer.GetAdornerLayer(element);
        var adorners = adornerLayer?.GetAdorners(element);

        if (adorners is null)
        {
            return;
        }

        foreach (var adorner in adorners.OfType<TAdorner>())
        {
            adornerLayer!.Remove(adorner);
        }

View on GitHub (pinned to 98edec3a0b)

Solutions

  1. Defer `AddAdorner` until the element's `Loaded` event (or `OnContentRendered` of the window), guaranteeing an adorner layer exists.
  2. Check `AdornerLayer.GetAdornerLayer(element) != null` before calling, and retry on `LayoutUpdated`/`Loaded` if null.
  3. Ensure the element is parented in a visible window when you adorn it.
  4. Remove adorners in `Unloaded`/`Closed` to avoid stale references when the tree is torn down.

Example fix

// before
var layer = AdornerLayer.GetAdornerLayer(tb); // null in ctor -> throws later
myAdorner...; tb.AddAdorner(new MyAdorner(tb));

// after
tb.Loaded += (s, e) =>
{
    if (AdornerLayer.GetAdornerLayer(tb) is { } layer)
        layer.Add(new MyAdorner(tb));
};
Defensive patterns

Strategy: validation

Validate before calling

void SafeAddAdorner(UIElement element, Adorner adorner)
{
    if (AdornerLayer.GetAdornerLayer(element) is { } layer)
        layer.Add(adorner);
    else
        element.Loaded += (s, _) => AdornerLayer.GetAdornerLayer(element)?.Add(adorner);
}

Type guard

static bool HasAdornerLayer(UIElement element)
    => AdornerLayer.GetAdornerLayer(element) is not null;

Prevention

When it happens

Trigger: Calling `element.AddAdorner(adorner)` on a `UIElement` that is not yet in the visual tree, before `Loaded`, after being removed from its parent, or on an element in a disconnected `UserControl`/popup.

Common situations: Attaching adorners in the constructor or `Initialized` instead of `Loaded`; adorning a templated element before template application; adorning an element whose window was closed; adorning inside a `Popup` before it is shown.

Related errors


AI-assisted analysis of MaterialDesignInXAML/MaterialDesignInXamlToolkit@98edec3a0b (2026-08-13). Data as JSON: /api/errors/781f00893a1febb3. Report an issue: GitHub.