Browse Source

Merge pull request #9012 from wieslawsoltes/SetAdronerFromXaml

Set control adorner from xaml
disbar
Jumar Macato 3 years ago
committed by GitHub
parent
commit
90012062fe
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      samples/ControlCatalog/MainView.xaml
  2. 66
      samples/ControlCatalog/Pages/AdornerLayerPage.xaml
  3. 48
      samples/ControlCatalog/Pages/AdornerLayerPage.xaml.cs
  4. 111
      src/Avalonia.Controls/Primitives/AdornerLayer.cs

3
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>

66
samples/ControlCatalog/Pages/AdornerLayerPage.xaml

@ -0,0 +1,66 @@
<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">
<DockPanel>
<Grid ColumnDefinitions="Auto,*" RowDefinitions="Auto" Margin="16" DockPanel.Dock="Top">
<TextBlock Grid.Column="0" Grid.Row="0">Rotation</TextBlock>
<Slider Name="rotation" Maximum="360" Grid.Column="1" Grid.Row="0"/>
</Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" DockPanel.Dock="Top">
<Button Name="AddAdorner"
Click="AddAdorner_OnClick"
Content="Add Adorner"
Margin="6" />
<Button Name="RemoveAdorner"
Click="RemoveAdorner_OnClick"
Content="Remove Adorner"
Margin="6" />
</StackPanel>
<Grid ColumnDefinitions="24,Auto,24"
RowDefinitions="24,Auto,24"
HorizontalAlignment="Center"
VerticalAlignment="Center">
<Border Background="{DynamicResource SystemAccentColor}" Grid.Column="1" Grid.Row="0"/>
<Border Background="{DynamicResource SystemAccentColor}" Grid.Column="0" Grid.Row="1"/>
<Border Background="{DynamicResource SystemAccentColor}" Grid.Column="2" Grid.Row="1"/>
<Border Background="{DynamicResource SystemAccentColor}" Grid.Column="1" Grid.Row="2"/>
<LayoutTransformControl Name="layoutTransform" Grid.Column="1" Grid.Row="1">
<LayoutTransformControl.LayoutTransform>
<RotateTransform Angle="{Binding #rotation.Value}"/>
</LayoutTransformControl.LayoutTransform>
<Button Name="AdornerButton"
Content="Adorned Button"
HorizontalAlignment="Stretch" HorizontalContentAlignment="Center"
VerticalContentAlignment="Center" VerticalAlignment="Stretch"
Width="200" Height="42">
<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>
</LayoutTransformControl>
</Grid>
</DockPanel>
</UserControl>

48
samples/ControlCatalog/Pages/AdornerLayerPage.xaml.cs

@ -0,0 +1,48 @@
using Avalonia.Controls;
using Avalonia.Controls.Primitives;
using Avalonia.Interactivity;
using Avalonia.Markup.Xaml;
namespace ControlCatalog.Pages
{
public class AdornerLayerPage : UserControl
{
private Control? _adorner;
public AdornerLayerPage()
{
this.InitializeComponent();
}
private void InitializeComponent()
{
AvaloniaXamlLoader.Load(this);
}
private void RemoveAdorner_OnClick(object? sender, RoutedEventArgs e)
{
var adornerButton = this.FindControl<Button>("AdornerButton");
if (adornerButton is { })
{
var adorner = AdornerLayer.GetAdorner(adornerButton);
if (adorner is { })
{
_adorner = adorner;
}
AdornerLayer.SetAdorner(adornerButton, null);
}
}
private void AddAdorner_OnClick(object? sender, RoutedEventArgs e)
{
var adornerButton = this.FindControl<Button>("AdornerButton");
if (adornerButton is { })
{
if (_adorner is { })
{
AdornerLayer.SetAdorner(adornerButton, _adorner);
}
}
}
}
}

111
src/Avalonia.Controls/Primitives/AdornerLayer.cs

@ -27,12 +27,22 @@ 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");
private static readonly AttachedProperty<AdornerLayer?> s_savedAdornerLayerProperty =
AvaloniaProperty.RegisterAttached<Visual, Visual, AdornerLayer?>("SavedAdornerLayer");
static AdornerLayer()
{
AdornedElementProperty.Changed.Subscribe(AdornedElementChanged);
AdornerProperty.Changed.Subscribe(AdornerChanged);
}
public AdornerLayer()
@ -65,6 +75,107 @@ 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);
}
private static void AdornerChanged(AvaloniaPropertyChangedEventArgs<Control?> e)
{
if (e.Sender is Visual visual)
{
var oldAdorner = e.OldValue.GetValueOrDefault();
var newAdorner = e.NewValue.GetValueOrDefault();
if (Equals(oldAdorner, newAdorner))
{
return;
}
if (oldAdorner is { })
{
visual.AttachedToVisualTree -= VisualOnAttachedToVisualTree;
visual.DetachedFromVisualTree -= VisualOnDetachedFromVisualTree;
Detach(visual, oldAdorner);
}
if (newAdorner is { })
{
visual.AttachedToVisualTree += VisualOnAttachedToVisualTree;
visual.DetachedFromVisualTree += VisualOnDetachedFromVisualTree;
Attach(visual, newAdorner);
}
}
}
private static void VisualOnAttachedToVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{
if (sender is Visual visual)
{
var adorner = GetAdorner(visual);
if (adorner is { })
{
Attach(visual, adorner);
}
}
}
private static void VisualOnDetachedFromVisualTree(object? sender, VisualTreeAttachmentEventArgs e)
{
if (sender is Visual visual)
{
var adorner = GetAdorner(visual);
if (adorner is { })
{
Detach(visual, adorner);
}
}
}
private static void Attach(Visual visual, Control adorner)
{
var layer = AdornerLayer.GetAdornerLayer(visual);
AddVisualAdorner(visual, adorner, layer);
visual.SetValue(s_savedAdornerLayerProperty, layer);
}
private static void Detach(Visual visual, Control adorner)
{
var layer = visual.GetValue(s_savedAdornerLayerProperty);
RemoveVisualAdorner(visual, adorner, layer);
visual.ClearValue(s_savedAdornerLayerProperty);
}
private static void AddVisualAdorner(Visual visual, Control? adorner, AdornerLayer? layer)
{
if (adorner is null || layer == null || layer.Children.Contains(adorner))
{
return;
}
AdornerLayer.SetAdornedElement(adorner, visual);
AdornerLayer.SetIsClipEnabled(adorner, false);
((ISetLogicalParent) adorner).SetParent(visual);
layer.Children.Add(adorner);
}
private static void RemoveVisualAdorner(Visual visual, Control? adorner, AdornerLayer? layer)
{
if (adorner is null || 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)

Loading…
Cancel
Save