using System; using Avalonia.Controls; using Avalonia.Controls.Primitives; using Avalonia.Metadata; using Avalonia.Xaml.Interactivity; namespace Avalonia.Xaml.Interactions.Custom; /// /// An action that displays a for the associated control when executed. /// /// If the associated control is of type than popup inherits control . public class PopupAction : Avalonia.Xaml.Interactivity.Action { private Popup? _popup; /// /// Identifies the avalonia property. /// public static readonly StyledProperty ChildProperty = AvaloniaProperty.Register(nameof(Child)); /// /// Gets or sets the popup Child control. This is a avalonia property. /// [Content] public Control? Child { get => GetValue(ChildProperty); set => SetValue(ChildProperty, value); } /// /// Executes the action. /// /// The that is passed to the action by the behavior. Generally this is or a target object. /// The value of this parameter is determined by the caller. /// Returns null after executed. public override object? Execute(object? sender, object? parameter) { if (!IsEnabled) { return false; } if (_popup is null) { var parent = sender as Control; _popup = new Popup() { Placement = PlacementMode.Pointer, PlacementTarget = parent, IsLightDismissEnabled = true }; if (sender is Control control) { BindToDataContext(control, _popup); } ((ISetLogicalParent)_popup).SetParent(parent); } _popup.Child = Child; _popup.Open(); return null; } private static void BindToDataContext(Control source, Control target) { if (source is null) { throw new ArgumentNullException(nameof(source)); } if (target is null) { throw new ArgumentNullException(nameof(target)); } var data = source.GetObservable(StyledElement.DataContextProperty); if (data is not null) { target.Bind(StyledElement.DataContextProperty, data); } } }