namespace Avalonia.Controls { using Input; using Interactivity; using LogicalTree; using Primitives; using System; using System.Reactive.Linq; using System.Linq; public class ContextMenu : SelectingItemsControl { private bool _isOpen; private Popup _popup; /// /// Initializes static members of the class. /// static ContextMenu() { ContextMenuProperty.Changed.Subscribe(ContextMenuChanged); MenuItem.ClickEvent.AddClassHandler(x => x.OnContextMenuClick, handledEventsToo: true); } /// /// Called when the property changes on a control. /// /// The event args. private static void ContextMenuChanged(AvaloniaPropertyChangedEventArgs e) { var control = (Control)e.Sender; if (e.OldValue != null) { control.PointerReleased -= ControlPointerReleased; } if (e.NewValue != null) { control.PointerReleased += ControlPointerReleased; } } /// /// Called when a submenu is clicked somewhere in the menu. /// /// The event args. private void OnContextMenuClick(RoutedEventArgs e) { Hide(); FocusManager.Instance.Focus(null); e.Handled = true; } /// /// Closes the menu. /// public void Hide() { if (_popup != null && _popup.IsVisible) { _popup.Close(); } SelectedIndex = -1; _isOpen = false; } /// /// Shows a context menu for the specified control. /// /// The control. private void Show(Control control) { if (control != null) { if (_popup == null) { _popup = new Popup() { PlacementMode = PlacementMode.Pointer, PlacementTarget = control, StaysOpen = false, ObeyScreenEdges = true }; _popup.Closed += PopupClosed; } ((ISetLogicalParent)_popup).SetParent(control); _popup.Child = control.ContextMenu; _popup.Open(); control.ContextMenu._isOpen = true; } } private static void PopupClosed(object sender, EventArgs e) { var contextMenu = (sender as Popup)?.Child as ContextMenu; if (contextMenu != null) { foreach (var i in contextMenu.GetLogicalChildren().OfType()) { i.IsSubMenuOpen = false; } contextMenu._isOpen = false; contextMenu.SelectedIndex = -1; } } private static void ControlPointerReleased(object sender, PointerReleasedEventArgs e) { var control = (Control)sender; var contextMenu = control.ContextMenu; if (e.MouseButton == MouseButton.Right) { if (control.ContextMenu._isOpen) { control.ContextMenu.Hide(); } contextMenu.Show(control); e.Handled = true; } else if (contextMenu._isOpen) { control.ContextMenu.Hide(); e.Handled = true; } } } }