Cross-platform solution for Right click context menu on desktop app
See original GitHub issueContext-menu support in .NET MAUI
A context menu, often known as a right-click menu, offers contextual commands that are specific to the element being clicked on. In .NET MAUI a context menu can be added to any control that is a View
, which includes all the controls that “take up space on the screen,” such as Label
, Entry
, Image
, Button
, WebView
, and many others.
Target platforms
- Windows: Fully supported
- MacCatalyst: Fully supported
- Other platforms: We will consider Android and iOS support at a later time
Note that even on supported platforms there are differences due to what each platform supports in their native context menu support.
New APIs
The main new API is a new ContextFlyout
property on the View
base type, via a new IContextFlyoutContainer
interface. The pattern is very similar to how a MenuBarItem
contains various flyout menu items.
Compatible menu flyout types and properties
Type | Windows properties | MacCatalyst properties |
---|---|---|
MenuFlyoutItem for menu items you can click |
Text , IconImageSource , Clicked , Command[Parameter] |
Text , ~IconImageSource ~, Clicked , Command[Parameter] |
MenuFlyoutSubItem to contain sub-menu items |
Text |
Text |
MenuFlyoutSeparator for horizontal lines |
N/A | N/A |
Usage examples and screenshots
A simple context menu to enable right-click support on a label has XAML like this:
<Label Text="Right-click to pick my color" x:Name="ColorLabel">
<Label.ContextActions>
<MenuFlyoutItem Text="Make label red" Clicked="MakeLabelRed"></MenuFlyoutItem>
<MenuFlyoutItem Text="Make label blue" Clicked="MakeLabelBlue"></MenuFlyoutItem>
</Label.ContextActions>
</Label>
And some C# code to handle the events like this:
private void MakeLabelRed(object sender, EventArgs e) => ColorLabel.BackgroundColor = Colors.Red;
private void MakeLabelBlue(object sender, EventArgs e) => ColorLabel.BackgroundColor = Colors.LightBlue;
And this is what it looks like on Windows:
And slightly more advanced with sub-menus and icons in XAML:
<Label Text="Right-click to pick my color" x:Name="ColorLabel">
<Label.ContextActions>
<MenuFlyoutItemText="Make label red" Clicked="MakeLabelRed">
<MenuFlyoutItem.IconImageSource>
<FontImageSource Glyph="X" FontFamily="Arial" Color="Red" />
</MenuFlyoutItem.IconImageSource>
</MenuFlyoutItem>
<MenuFlyoutItem Text="Make label blue" Clicked="MakeLabelBlue">
<MenuFlyoutItem.IconImageSource>
<FontImageSource Glyph="X" FontFamily="Arial" Color="Blue" />
</MenuFlyoutItem.IconImageSource>
</MenuFlyoutItem>
<MenuFlyoutSubItem Text="More colors">
<MenuFlyoutItem Text="Hot pink" Clicked="MakeLabelHotPink">
<MenuItem.IconImageSource>
<FontImageSource Glyph="X" FontFamily="Arial" Color="HotPink" />
</MenuItem.IconImageSource>
</MenuFlyoutItem>
<MenuFlyoutItem Text="Pale Goldenrod" Clicked="MakeLabelPaleGoldenrod">
<MenuItem.IconImageSource>
<FontImageSource Glyph="X" FontFamily="Arial" Color="PaleGoldenrod" />
</MenuItem.IconImageSource>
</MenuFlyoutItem>
</MenuFlyoutSubItem>
</Label.ContextActions>
</Label>
And similar C# event handlers:
private void MakeLabelRed(object sender, EventArgs e) => ColorLabel.BackgroundColor = Colors.Red;
private void MakeLabelBlue(object sender, EventArgs e) => ColorLabel.BackgroundColor = Colors.LightBlue;
private void MakeLabelHotPink(object sender, EventArgs e) => ColorLabel.BackgroundColor = Colors.HotPink;
private void MakeLabelPaleGoldenrod(object sender, EventArgs e) => ColorLabel.BackgroundColor = Colors.PaleGoldenrod;
And you get this lovely user interface on Windows:
And similarly on MacOS (note that there are no icons supported):
Custom context menus with Entry (textbox)
- On Windows, this works automatically
- On MacOS this does not yet work (you always get the default MacOS menu with clipboard functions, etc.)
Custom context menus with WebView
- On Windows you need code like this to disable WebView2’s default menu:
// In the constructor, after calling InitializeComponent(); #if WINDOWS ContextMenuWebView.HandlerChanged += OnWebViewHandlerChanged; #endif #if WINDOWS void OnWebViewHandlerChanged(object sender, EventArgs e) { if (ContextMenuWebView.Handler != null) { var webView2 = (Microsoft.UI.Xaml.Controls.WebView2)ContextMenuWebView.Handler.PlatformView; webView2.CoreWebView2Initialized += OnWebView2CoreWebView2Initialized; } } private void OnWebView2CoreWebView2Initialized(Microsoft.UI.Xaml.Controls.WebView2 sender, Microsoft.UI.Xaml.Controls.CoreWebView2InitializedEventArgs args) { sender.CoreWebView2.Settings.AreDefaultContextMenusEnabled = false; } #endif
- On MacOS this is being investigated.
Custom context menu location
Not yet supported. The context menu shows up exactly where the pointer was right-clicked, and opens in the appropriate orientation for the device.
Dynamic context menu items
Changing the contents of the context menus dynamically is not fully supported at this time. The code in the PR contains some comments to that effect. It should be implemented in both Windows and macOS.
Using {Binding ...}
for context menu items
There are some limitations with binding in menu items. This is related to the following issues:
- Command bound with MenuFlyoutItem is not getting executed, whereas Clicked event is working fine #5382
- Draft PR here: Preserve the correct binding context for menu items #7358
- Possible fix also as seen here: https://github.com/dotnet/maui/blob/main/src/Controls/src/Core/BindableObject.cs#L264-L275
Original Description
Description
Right-click context menus are a very very important feature for desktop apps. Almost every desktop app needs this feature. But I don’t think there is a cross-platform way to do it in MAUI.
Public API Changes
Have to introduce a new control for the context menu like other desktop frameworks.
Intended Use-Case
This can be very useful for providing desktop-specific options or when you are building a desktop-only app with MAUI
Issue Analytics
- State:
- Created a year ago
- Reactions:9
- Comments:17 (9 by maintainers)
Top GitHub Comments
It’s hardly even a prototype, but I think we can make this work! At least, on Windows for now!
I hard-coded a ton of stuff, but this is a right-click context menu on a label:
We’ve moved this issue to the Future milestone. This means that it is not going to be worked on for the coming release. We will reassess the issue following the current release and consider this item at that time.