1
0
Эх сурвалжийг харах

Set control adorner from xaml

Wiesław Šoltés 3 жил өмнө
parent
commit
8351932bf6

+ 3 - 0
samples/ControlCatalog/MainView.xaml

@@ -19,6 +19,9 @@
       <TabItem Header="Acrylic">
         <pages:AcrylicPage />
       </TabItem>
+      <TabItem Header="AdornerLayer">
+        <pages:AdornerLayerPage />
+      </TabItem>
       <TabItem Header="AutoCompleteBox">
         <pages:AutoCompleteBoxPage />
       </TabItem>

+ 30 - 0
samples/ControlCatalog/Pages/AdornerLayerPage.xaml

@@ -0,0 +1,30 @@
+<UserControl x:Class="ControlCatalog.Pages.AdornerLayerPage"
+             xmlns="https://github.com/avaloniaui"
+             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
+             xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
+             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
+             d:DesignHeight="800"
+             d:DesignWidth="400"
+             mc:Ignorable="d">
+  <Grid RowDefinitions="100,42,*" ColumnDefinitions="50,200,*">
+    <Button Content="Adorned Button" 
+            HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
+            VerticalContentAlignment="Center" VerticalAlignment="Stretch" 
+            Grid.Row="1" Grid.Column="1">
+      <AdornerLayer.Adorner>
+        <Canvas x:Name="AdornerCanvas"
+                HorizontalAlignment="Stretch"
+                VerticalAlignment="Stretch"
+                Background="Cyan"
+                IsHitTestVisible="False"
+                Opacity="0.3"
+                IsVisible="True">
+          <Line StartPoint="-10000,0" EndPoint="10000,0" Stroke="Cyan" StrokeThickness="1" />
+          <Line StartPoint="-10000,42" EndPoint="10000,42" Stroke="Cyan" StrokeThickness="1" />
+          <Line StartPoint="0,-10000" EndPoint="0,10000" Stroke="Cyan" StrokeThickness="1" />
+          <Line StartPoint="200,-10000" EndPoint="200,10000" Stroke="Cyan" StrokeThickness="1" />
+        </Canvas>
+      </AdornerLayer.Adorner>
+    </Button>
+  </Grid>
+</UserControl>

+ 19 - 0
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);
+        }
+    }
+}

+ 72 - 0
src/Avalonia.Controls/Primitives/AdornerLayer.cs

@@ -27,6 +27,12 @@ namespace Avalonia.Controls.Primitives
         public static readonly AttachedProperty<bool> IsClipEnabledProperty =
             AvaloniaProperty.RegisterAttached<AdornerLayer, Visual, bool>("IsClipEnabled", true);
 
+        /// <summary>
+        /// Allows for getting and setting of the adorner for control.
+        /// </summary>
+        public static readonly AttachedProperty<Control?> AdornerProperty =
+            AvaloniaProperty.RegisterAttached<AdornerLayer, Visual, Control?>("Adorner");
+
         private static readonly AttachedProperty<AdornedElementInfo> s_adornedElementInfoProperty =
             AvaloniaProperty.RegisterAttached<AdornerLayer, Visual, AdornedElementInfo>("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)