Skip to content

Context Menu

ContextMenu is a small family (two new classes) that opens a native ContextMenu anchored at the pointer through WPF’s own ContextMenuService, reusing the Menu family’s NaviusMenuItem/ NaviusMenuCheckboxItem/NaviusMenuRadioItem/NaviusMenuGroupLabel and the general-purpose NaviusSeparator verbatim rather than duplicating near-identical item classes. Right-click, Shift+F10, and the keyboard Apps/Menu key all open the popup for free through ContextMenuService.

xmlns:contextmenu="clr-namespace:Navius.Wpf.Primitives.Controls.ContextMenu;assembly=Navius.Wpf.Primitives"
xmlns:menu="clr-namespace:Navius.Wpf.Primitives.Controls.Menus;assembly=Navius.Wpf.Primitives"
<Window.Resources>
<contextmenu:NaviusContextMenuPopup x:Key="RowMenu">
<menu:NaviusMenuItem Header="Rename" />
<menu:NaviusMenuItem Header="Delete" />
</contextmenu:NaviusContextMenuPopup>
</Window.Resources>
<contextmenu:NaviusContextMenuTrigger Menu="{StaticResource RowMenu}">
<TextBlock Text="Right-click this row" />
</contextmenu:NaviusContextMenuTrigger>
Property Type Default From Description
Menu NaviusContextMenuPopup? null NaviusContextMenuTrigger Assigns straight onto FrameworkElement.ContextMenu.
Disabled bool false NaviusContextMenuTrigger Maps onto ContextMenuService.SetIsEnabled(this, !value), not IsEnabled, so the element stays interactive while the menu is suppressed.
Side PlacementSide Right NaviusContextMenuPopup Only used by RequestOpenAt; right-click/keyboard opens use ContextMenuService’s own PlacementMode.MousePoint for free.
Align PlacementAlign Start NaviusContextMenuPopup Only used by RequestOpenAt.
Method Description
RequestOpenAt(UIElement target, Point pointRelativeToTarget) Opens the popup anchored at an explicit point (switches to PlacementMode.Custom for that one open, reusing the same PlacementMath-based offset math as NaviusMenuPopup). The direct mapping of the contract’s Open(point) API, for a custom gesture or non-cursor anchor; right-click/Shift+F10/menu-key opens do not call this.

The shared item stack behaves exactly as in Menu (roving Arrow keys, Home, typeahead via TextSearch.Text, submenu via native nesting, Escape); see menu.md. Opening itself is native ContextMenuService behavior:

Key Behavior
Shift + F10 / the keyboard Apps/Menu key Opens the menu anchored at the trigger element’s own rect (native ContextMenuService).
Right-click Opens the menu anchored at the pointer (native PlacementMode.MousePoint).

NaviusContextMenuPopup ships no custom automation peer, inheriting the native ContextMenu automation peer. Items inherit MenuItemAutomationPeer exactly as in the Menu family, since this family reuses those classes verbatim. The unit suite (ContextMenuTests.cs, 6 facts) covers template application for the two new classes, Menu assignment reflecting onto FrameworkElement.ContextMenu, Disabled toggling ContextMenuService.IsEnabled, and the Side/Align defaults. RequestOpenAt’s actual popup-opening behavior is exercised interactively via the gallery rather than a headless test, since it requires a live PresentationSource on the placement target.

  • The web contract’s 23 parts (Root/Trigger/Portal/Positioner/Popup/Arrow/Group/Label/Item/ CheckboxItem/RadioGroup/RadioItem/ItemIndicator/Separator/Sub/SubTrigger/SubContent) collapse onto exactly two new classes (Trigger, Popup) plus the Menu family’s reused item stack; no separate Portal/Positioner/Arrow types exist (Portal is a no-op, Positioner folds onto Side/Align on the Popup, Arrow is not implemented).
  • NaviusContextMenuPortal’s Container (a CSS mount-point selector) has no WPF equivalent and is dropped; WPF popups already float in their own window layer.
  • Long-press-to-open on touch is not implemented: ContextMenuService has no built-in long-press gesture, and a custom TouchDown/Stylus timer was out of scope.
  • Modal is not implemented: native Popup’s default outside-click dismissal and Escape-to-close already cover the practical behavior; no scroll-lock equivalent was added.
  • RequestOpenAt is a synchronous method, not async, since opening at an explicit point needs no interop round-trip in WPF (unlike the web contract’s JS-interop-backed Open(point)).

The Context Menu Gallery page rendered at the pinned commit, in each theme.

Context Menu Gallery page in the light theme

Context Menu Gallery page in the dark theme

Context Menu Gallery page in the high contrast theme