Menu
The
Menu
control adds a top-level menu to an application. A Menu
is usually placed in a DockPanel
in a Window
, docked to the top of the window:<Window xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="_File">
<MenuItem Header="_Open..."/>
<Separator/>
<MenuItem Header="_Exit"/>
</MenuItem>
<MenuItem Header="_Edit">
<MenuItem Header="Copy"/>
<MenuItem Header="Paste"/>
</MenuItem>
</Menu>
</DockPanel>
</Window>
A menu will usually contain a set of nested
MenuItem
s. The first level of MenuItem
s represent the items that will be displayed horizontally along the menu. The second level of MenuItem
s represent the menu items that will be dropped down from the top-level and subsequent nested MenuItem
s represent sub-menus.The text of the
MenuItem
is displayed by the Header
property; the inner content of the MenuItem
is where the sub-items are placed.Separators are added by including a
Separator
control or a MenuItem
with a header of "-"
.An accelerator key is a key on your keyboard that you can press to quickly access a menu. It is also sometimes called a hot key, access key or mnemonic.
If you will press Alt with the example above you will see that some letters are underlined. You can use a combination of Alt + underlined letter to navigate within a menu. In Avalonia to identify the accelerator key, you will need to use
_
next character to this character would be an accelerator key.Like
Button
, commands can be bound to MenuItem
s. The command will be executed when the menu item is clicked or selected with the keyboard:<Menu>
<MenuItem Header="_File">
<MenuItem Header="_Open..." Command="{Binding OpenCommand}"/>
</MenuItem>
</Menu>
A menu icon can be displayed by placing an
Image
in the Icon
property: <MenuItem Header="_Open...">
<MenuItem.Icon>
<Image Source="resm:MyApp.Assets.Open.png"/>
</MenuItem.Icon>
</MenuItem>
Similarly, a
CheckBox
can be displayed in the Icon
property to make the MenuItem
checkable: <MenuItem Header="_Open...">
<MenuItem.Icon>
<CheckBox BorderThickness="0"
IsHitTestVisible="False"
Command="{Binding ToggleCommand}">
Toggle _Me
</CheckBox>
</MenuItem.Icon>
</MenuItem>
Menus can also be dynamically created using bindings and
DataTemplate
s. To do this, you will usually create a view model to represent your Window
with a set of commands relating to the menu commands:public class MainWindowViewModel
{
public MainWindowViewModel()
{
OpenCommand = ReactiveCommand.CreateFromTask(Open);
SaveCommand = ReactiveCommand.Create(Save);
OpenRecentCommand = ReactiveCommand.Create<string>(OpenRecent);
}
public IReadOnlyList<MenuItemViewModel> MenuItems { get; set; }
public ReactiveCommand<Unit, Unit> OpenCommand { get; }
public ReactiveCommand<Unit, Unit> SaveCommand { get; }
public ReactiveCommand<string, Unit> OpenRecentCommand { get; }
public async Task Open()
{
var dialog = new OpenFileDialog();
var result = await dialog.ShowAsync();
if (result != null)
{
foreach (var path in result)
{
System.Diagnostics.Debug.WriteLine($"Opened: {path}");
}
}
}
public void Save()
{
System.Diagnostics.Debug.WriteLine("Save");
}
public void OpenRecent(string path)
{
System.Diagnostics.Debug.WriteLine($"Open recent: {path}");
}
}
And a view model for the menu items
public class MenuItemViewModel
{
public string Header { get; set; }
public ICommand Command { get; set; }
public object CommandParameter { get; set; }
public IList<MenuItemViewModel> Items { get; set; }
}
Next, you can create your menu structure using the view models. The following code when placed in a
Window
constructor will create a basic menu structure and assign it to the Window
's DataContext
.public MainWindow()
{
InitializeComponent();
var vm = new MainWindowViewModel();
vm.MenuItems = new[]
{
new MenuItemViewModel
{
Header = "_File",
Items = new[]
{
new MenuItemViewModel { Header = "_Open...", Command = vm.OpenCommand },
new MenuItemViewModel { Header = "Save", Command = vm.SaveCommand },
new MenuItemViewModel { Header = "-" },
new MenuItemViewModel
{
Header = "Recent",
Items = new[]
{
new MenuItemViewModel
{
Header = "File1.txt",
Command = vm.OpenRecentCommand,
CommandParameter = @"c:\foo\File1.txt"
},
new MenuItemViewModel
{
Header = "File2.txt",
Command = vm.OpenRecentCommand,
CommandParameter = @"c:\foo\File2.txt"
},
}
},
}
},
new MenuItemViewModel
{
Header = "_Edit",
Items = new[]
{
new MenuItemViewModel { Header = "_Copy" },
new MenuItemViewModel { Header = "_Paste" },
}
}
};
DataContext = vm;
}
Finally assign the bindings to the view model in a
Style
within the menu:<Menu Items="{Binding MenuItems}">
<Menu.Styles>
<Style Selector="MenuItem">
<Setter Property="Header" Value="{Binding Header}"/>
<Setter Property="Items" Value="{Binding Items}"/>
<Setter Property="Command" Value="{Binding Command}"/>
<Setter Property="CommandParameter" Value="{Binding CommandParameter}"/>
</Style>
</Menu.Styles>
</Menu>
Last modified 1yr ago