namespace Perspex.Controls { using Input; using Interactivity; using LogicalTree; using Primitives; using System; using System.Reactive.Linq; public class ContextMenu : SelectingItemsControl { private bool _isOpen; /// /// Defines the ContextMenu.Menu attached property. /// //public static readonly AttachedProperty ContextMenuProperty = // PerspexProperty.RegisterAttached("Menu"); /// /// The popup window used to display the active context menu. /// private static PopupRoot s_popup; /// /// The control that the currently visible context menu is attached to. /// private static Control s_current; /// /// Initializes static members of the class. /// static ContextMenu() { ContextMenuProperty.Changed.Subscribe(ContextMenuChanged); MenuItem.ClickEvent.AddClassHandler(x => x.OnContextMenuClick); } /// /// Gets the value of the ToolTip.Tip attached property. /// /// The control to get the property from. /// /// The content to be displayed in the control's tooltip. /// public static object GetContextMenu(Control element) { return element.GetValue(ContextMenuProperty); } /// /// Sets the value of the ToolTip.Tip attached property. /// /// The control to get the property from. /// The content to be displayed in the control's tooltip. public static void SetContextMenu(Control element, object value) { element.SetValue(ContextMenuProperty, value); } /// /// called when the property changes on a control. /// /// The event args. private static void ContextMenuChanged(PerspexPropertyChangedEventArgs 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() { foreach (MenuItem i in this.GetLogicalChildren()) { i.IsSubMenuOpen = false; } if (s_popup != null && s_popup.IsVisible) { s_popup.Hide(); } SelectedIndex = -1; _isOpen = false; } /// /// Shows a tooltip for the specified control. /// /// The control. private static void Show(Control control) { if (control != null) { if (s_popup == null) { s_popup = new PopupRoot { Content = new ToolTip(), }; ((ISetLogicalParent)s_popup).SetParent(control); } var cp = MouseDevice.Instance?.GetPosition(control); var position = control.PointToScreen(cp ?? new Point(0, 0)); ((ToolTip)s_popup.Content).Content = GetContextMenu(control); s_popup.Position = position; s_popup.Show(); s_current = control; control.ContextMenu._isOpen = true; } } private static void ControlPointerReleased(object sender, PointerReleasedEventArgs e) { var control = (Control)sender; if (e.MouseButton == MouseButton.Right) { if(control.ContextMenu._isOpen) { control.ContextMenu.Hide(); } Show(control); } else { control.ContextMenu.Hide(); } } } }