PopupAction.cs 2.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. using System;
  2. using Avalonia.Controls;
  3. using Avalonia.Controls.Primitives;
  4. using Avalonia.Metadata;
  5. using Avalonia.Xaml.Interactivity;
  6. namespace Avalonia.Xaml.Interactions.Custom;
  7. /// <summary>
  8. /// An action that displays a <see cref="Popup"/> for the associated control when executed.
  9. /// </summary>
  10. /// <remarks>If the associated control is of type <see cref="Control"/> than popup inherits control <see cref="StyledElement.DataContext"/>.</remarks>
  11. public class PopupAction : Avalonia.Xaml.Interactivity.Action
  12. {
  13. private Popup? _popup;
  14. /// <summary>
  15. /// Identifies the <seealso cref="ChildProperty"/> avalonia property.
  16. /// </summary>
  17. public static readonly StyledProperty<Control?> ChildProperty =
  18. AvaloniaProperty.Register<PopupAction, Control?>(nameof(Child));
  19. /// <summary>
  20. /// Gets or sets the popup Child control. This is a avalonia property.
  21. /// </summary>
  22. [Content]
  23. public Control? Child
  24. {
  25. get => GetValue(ChildProperty);
  26. set => SetValue(ChildProperty, value);
  27. }
  28. /// <summary>
  29. /// Executes the action.
  30. /// </summary>
  31. /// <param name="sender">The <see cref="object"/> that is passed to the action by the behavior. Generally this is <seealso cref="IBehavior.AssociatedObject"/> or a target object.</param>
  32. /// <param name="parameter">The value of this parameter is determined by the caller.</param>
  33. /// <returns>Returns null after executed.</returns>
  34. public override object? Execute(object? sender, object? parameter)
  35. {
  36. if (!IsEnabled)
  37. {
  38. return false;
  39. }
  40. if (_popup is null)
  41. {
  42. var parent = sender as Control;
  43. _popup = new Popup()
  44. {
  45. Placement = PlacementMode.Pointer, PlacementTarget = parent, IsLightDismissEnabled = true
  46. };
  47. if (sender is Control control)
  48. {
  49. BindToDataContext(control, _popup);
  50. }
  51. ((ISetLogicalParent)_popup).SetParent(parent);
  52. }
  53. _popup.Child = Child;
  54. _popup.Open();
  55. return null;
  56. }
  57. private static void BindToDataContext(Control source, Control target)
  58. {
  59. if (source is null)
  60. {
  61. throw new ArgumentNullException(nameof(source));
  62. }
  63. if (target is null)
  64. {
  65. throw new ArgumentNullException(nameof(target));
  66. }
  67. var data = source.GetObservable(StyledElement.DataContextProperty);
  68. if (data is not null)
  69. {
  70. target.Bind(StyledElement.DataContextProperty, data);
  71. }
  72. }
  73. }