diff --git a/samples/ControlCatalog/MainView.xaml b/samples/ControlCatalog/MainView.xaml index 7f5a191519..ec198c6bba 100644 --- a/samples/ControlCatalog/MainView.xaml +++ b/samples/ControlCatalog/MainView.xaml @@ -19,6 +19,9 @@ + + + diff --git a/samples/ControlCatalog/Pages/AdornerLayerPage.xaml b/samples/ControlCatalog/Pages/AdornerLayerPage.xaml new file mode 100644 index 0000000000..853bae4695 --- /dev/null +++ b/samples/ControlCatalog/Pages/AdornerLayerPage.xaml @@ -0,0 +1,30 @@ + + + + + diff --git a/samples/ControlCatalog/Pages/AdornerLayerPage.xaml.cs b/samples/ControlCatalog/Pages/AdornerLayerPage.xaml.cs new file mode 100644 index 0000000000..2a9e5bf9ba --- /dev/null +++ b/samples/ControlCatalog/Pages/AdornerLayerPage.xaml.cs @@ -0,0 +1,19 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace ControlCatalog.Pages +{ + public class AdornerLayerPage : UserControl + { + public AdornerLayerPage() + { + this.InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } + } +} diff --git a/src/Avalonia.Controls/Primitives/AdornerLayer.cs b/src/Avalonia.Controls/Primitives/AdornerLayer.cs index 57fb7226e8..51975ccd1a 100644 --- a/src/Avalonia.Controls/Primitives/AdornerLayer.cs +++ b/src/Avalonia.Controls/Primitives/AdornerLayer.cs @@ -27,6 +27,12 @@ namespace Avalonia.Controls.Primitives public static readonly AttachedProperty IsClipEnabledProperty = AvaloniaProperty.RegisterAttached("IsClipEnabled", true); + /// + /// Allows for getting and setting of the adorner for control. + /// + public static readonly AttachedProperty AdornerProperty = + AvaloniaProperty.RegisterAttached("Adorner"); + private static readonly AttachedProperty s_adornedElementInfoProperty = AvaloniaProperty.RegisterAttached("AdornedElementInfo"); @@ -65,6 +71,72 @@ namespace Avalonia.Controls.Primitives adorner.SetValue(IsClipEnabledProperty, isClipEnabled); } + public static Control? GetAdorner(Visual visual) + { + return visual.GetValue(AdornerProperty); + } + + public static void SetAdorner(Visual visual, Control? adorner) + { + visual.SetValue(AdornerProperty, adorner); + + SetVisualAdorner(visual, adorner); + } + + private static void SetVisualAdorner(Visual visual, Control? adorner) + { + var layer = default(AdornerLayer); + + visual.AttachedToVisualTree += (_, _) => + { + layer = AddVisualAdorner(visual, adorner); + }; + + visual.DetachedFromVisualTree += (_, _) => + { + RemoveVisualAdorner(visual, adorner, layer); + }; + } + + private static AdornerLayer? AddVisualAdorner(Visual visual, Control? adorner) + { + if (adorner is null) + { + return null; + } + + var layer = AdornerLayer.GetAdornerLayer(visual); + if (layer == null || layer.Children.Contains(adorner)) + { + return layer; + } + + AdornerLayer.SetAdornedElement(adorner, visual); + AdornerLayer.SetIsClipEnabled(adorner, false); + + ((ISetLogicalParent) adorner).SetParent(visual); + layer.Children.Add(adorner); + + return layer; + } + + private static void RemoveVisualAdorner(Visual visual, Control? adorner, AdornerLayer? layer) + { + if (adorner is null) + { + return; + } + + // var layer = AdornerLayer.GetAdornerLayer(visual); + if (layer is null || !layer.Children.Contains(adorner)) + { + return; + } + + layer.Children.Remove(adorner); + ((ISetLogicalParent) adorner).SetParent(null); + } + protected override Size MeasureOverride(Size availableSize) { foreach (var child in Children)