NeedsUpdate) and Command StateNativeMenuBar Behavior and VisibilityPrimary APIs:
NativeMenuNativeMenuItemBaseNativeMenuItemNativeMenuItemSeparatorNativeMenuBarINativeMenuExporterAttached properties and helpers:
NativeMenu.MenuPropertyNativeMenu.SetMenu(...)NativeMenu.GetMenu(...)NativeMenu.IsNativeMenuExportedPropertyNativeMenu.GetIsNativeMenuExported(...)Important members:
NativeMenu.Items, NeedsUpdate, Opening, ClosedNativeMenuItem.Header, Menu, Command, CommandParameterNativeMenuItem.Gesture, ToggleType, IsChecked, IsEnabled, IsVisibleNativeMenuItem.Icon, ToolTip, ClickReference source files:
src/Avalonia.Controls/NativeMenu.cssrc/Avalonia.Controls/NativeMenu.Export.cssrc/Avalonia.Controls/NativeMenuItemBase.cssrc/Avalonia.Controls/NativeMenuItem.cssrc/Avalonia.Controls/NativeMenuItemSeparator.cssrc/Avalonia.Controls/NativeMenuBar.csAvalonia native menu integration works through NativeMenu.MenuProperty attached to a TopLevel (Window and other top-level hosts).
High-level flow:
NativeMenu to a top-level.NativeMenu.IsNativeMenuExportedProperty reflects exporter state.Important constraint:
IsNativeMenuExportedProperty is effectively read-only for app code. Do not set it directly.Use one NativeMenu model and show NativeMenuBar for platforms where native export is unavailable.
<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vm="using:MyApp.ViewModels"
x:DataType="vm:MainWindowViewModel">
<NativeMenu.Menu>
<NativeMenu>
<NativeMenuItem Header="_File">
<NativeMenuItem.Menu>
<NativeMenu>
<NativeMenuItem Header="_Open" Command="{Binding OpenCommand}" Gesture="Ctrl+O" />
<NativeMenuItem Header="_Save" Command="{Binding SaveCommand}" Gesture="Ctrl+S" />
<NativeMenuItemSeparator />
<NativeMenuItem Header="E_xit" Command="{Binding ExitCommand}" />
</NativeMenu>
</NativeMenuItem.Menu>
</NativeMenuItem>
<NativeMenuItem Header="_View">
<NativeMenuItem.Menu>
<NativeMenu>
<NativeMenuItem Header="Show _Grid"
ToggleType="CheckBox"
IsChecked="{Binding ShowGrid}" />
</NativeMenu>
</NativeMenuItem.Menu>
</NativeMenuItem>
</NativeMenu>
</NativeMenu.Menu>
<DockPanel>
<NativeMenuBar DockPanel.Dock="Top" />
<ContentPresenter Content="{Binding MainContent}" />
</DockPanel>
</Window>
NativeMenuBar binds itself to NativeMenu.Menu and hides automatically when native export is active.
using Avalonia.Controls;
using Avalonia.Input;
static NativeMenu BuildNativeMenu(MainWindowViewModel vm)
{
var fileMenu = new NativeMenuItem("_File") { Menu = new NativeMenu() };
fileMenu.Menu!.Add(new NativeMenuItem("_Open")
{
Command = vm.OpenCommand,
Gesture = KeyGesture.Parse("Ctrl+O")
});
fileMenu.Menu.Add(new NativeMenuItem("_Save")
{
Command = vm.SaveCommand,
Gesture = KeyGesture.Parse("Ctrl+S")
});
fileMenu.Menu.Add(new NativeMenuItemSeparator());
fileMenu.Menu.Add(new NativeMenuItem("E_xit") { Command = vm.ExitCommand });
return new NativeMenu { fileMenu };
}
static void AttachNativeMenu(Window window, MainWindowViewModel vm)
{
var menu = BuildNativeMenu(vm);
NativeMenu.SetMenu(window, menu);
}
NeedsUpdate) and Command StateNeedsUpdate is the preferred hook for changing menu structure/state before display or hotkey dispatch.
void WireDynamicState(NativeMenu menu, MainWindowViewModel vm)
{
menu.NeedsUpdate += (_, _) =>
{
// Keep updates here instead of Opening/Closed.
vm.RefreshRecentFilesMenu();
};
}
NativeMenuItem command-state behavior:
ICommand.CanExecuteChanged,IsEnabled on UI thread,Command when clicked (if CanExecute is true).NativeMenuBar Behavior and VisibilityNativeMenuBar is a TemplatedControl that:
NativeMenu.Menu,MenuBase presenter,!NativeMenu.IsNativeMenuExported.Practical meaning:
NativeMenu as the single source of truth for app menu structure.NativeMenuBar in desktop shells for non-exported fallback behavior.NeedsUpdate for dynamic menu population; avoid structure mutation in Opening/Closed.Command on NativeMenuItem; use Click only for small glue logic.NativeMenu.GetIsNativeMenuExported(topLevel) at runtime.ITopLevelNativeMenuExporter.NativeMenuBar never shows.
TopLevel where NativeMenu.Menu is set.Opening/Closed into NeedsUpdate.NativeMenu and its NativeMenuItemBase children can have only one parent at a time.