Primary APIs:
AdornerLayerAdornerLayer.GetAdornerLayer(...)AdornerLayer.AdornerPropertyAdornerLayer.AdornedElementPropertyAdornerLayer.IsClipEnabledPropertyAdornerLayer.DefaultFocusAdornerControl.FocusAdornerFocusAdornerTemplateVisualLayerManager.AdornerLayerReference source files:
src/Avalonia.Controls/Primitives/AdornerLayer.cssrc/Avalonia.Controls/Control.cssrc/Avalonia.Controls/Primitives/VisualLayerManager.cssrc/Markup/Avalonia.Markup.Xaml/Templates/FocusAdornerTemplate.cssrc/Avalonia.Themes.Fluent/Controls/AdornerLayer.xamlsrc/Avalonia.Themes.Simple/Controls/AdornerLayer.xamlsamples/ControlCatalog/Pages/AdornerLayerPage.xamlAdornerLayer is an overlay Canvas managed by VisualLayerManager.
Use cases:
Attachment model:
AdornerLayer.Adorner on the adorned visual.AdornerLayer.AdornedElement.Control focus visuals are adorner-backed:
Control.FocusAdorner provides per-control template override.AdornerLayer.DefaultFocusAdorner is used.This is why mouse focus may not show the same focus adorner behavior by default.
XAML pattern:
<Button xmlns="https://github.com/avaloniaui"
Content="Adorned Button">
<AdornerLayer.Adorner>
<Canvas IsHitTestVisible="False"
Background="#3300D4FF"
AdornerLayer.IsClipEnabled="False">
<Line StartPoint="-10000,0" EndPoint="10000,0" Stroke="#00D4FF" StrokeThickness="1" />
<Line StartPoint="0,-10000" EndPoint="0,10000" Stroke="#00D4FF" StrokeThickness="1" />
</Canvas>
</AdornerLayer.Adorner>
</Button>
Code pattern:
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Media;
var adorner = new Border
{
BorderBrush = Brushes.DeepSkyBlue,
BorderThickness = new Thickness(2),
IsHitTestVisible = false
};
AdornerLayer.SetIsClipEnabled(adorner, false);
AdornerLayer.SetAdorner(targetControl, adorner);
Remove adorner when done:
AdornerLayer.SetAdorner(targetControl, null);
AdornerLayer tracks adorned bounds and arranges overlays accordingly.
Important controls:
AdornerLayer.IsClipEnabled: clip to adorned bounds when true.Use IsClipEnabled="False" for crosshair/ruler overlays that intentionally extend outside bounds.
Override the default focus adorner template through AdornerLayer theme:
<ControlTheme xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Key="{x:Type AdornerLayer}"
TargetType="AdornerLayer">
<Setter Property="DefaultFocusAdorner">
<FocusAdornerTemplate>
<Border BorderThickness="2" BorderBrush="DodgerBlue" />
</FocusAdornerTemplate>
</Setter>
</ControlTheme>
Per-control opt-out:
<TextBox FocusAdorner="{x:Null}" />
IsHitTestVisible="False") unless interaction is required.AdornerLayer.Adorner not set or set to null.FocusAdorner and DefaultFocusAdorner are both unset/null.AdornerLayer.IsClipEnabled is still true.