# Menu 使用文档
本文档介绍 AtomUI Menu 控件家族的使用方式,涵盖 `Menu`(顶部菜单栏)、`MenuItem`(菜单项)、`ContextMenu`(右键菜单)、`MenuSeparator`(分隔线)和 `MenuFlyout`(弹出菜单)。
> 📖 Gallery 源码位置:`controlgallery/AtomUIGallery/ShowCases/Views/Navigation/MenuShowCase.axaml`
---
## 前置准备
### AXAML 命名空间
```xml
xmlns:atom="https://atomui.net"
xmlns:antdicons="https://atomui.net/icons/antdesign"
```
### C# 引用
```csharp
using AtomUI.Desktop.Controls;
```
---
## 1. 基本用法
最简单的菜单栏,包含顶层菜单项和嵌套子菜单。
> 📖 对应 Gallery:`MenuShowCase.axaml` → **"Basic"** ShowCaseItem
```xml
```
**要点:**
- `Header` 中的 `_` 前缀字符用于定义键盘访问键(Access Key)
- `InputGesture` 用于设置快捷键提示文本
- `MenuSeparator` 用于在菜单项之间插入分隔线
- `IsEnabled="False"` 设置禁用状态
---
## 2. 通过 ItemsSource 数据驱动生成菜单
使用数据模型和 `ItemTemplate` 动态生成菜单结构,适用于从后端数据或配置动态构建菜单。
> 📖 对应 Gallery:`MenuShowCase.axaml` → **"Generate MenuItem by ItemsSource"** ShowCaseItem
### AXAML
```xml
```
### ViewModel 数据构建
```csharp
using AtomUI.Desktop.Controls;
// 构建菜单数据
var menuItems = new List
{
new MenuItemData
{
Header = "File",
Children = new List
{
new MenuItemData { Header = "New Text File" },
new MenuItemData { Header = "New File" },
new MenuSeparatorData(), // 分隔线
new MenuItemData { Header = "Save" },
}
},
new MenuItemData
{
Header = "Edit",
Children = new List
{
new MenuItemData { Header = "Undo" },
new MenuItemData { Header = "Cut", IsEnabled = false },
}
}
};
// 绑定到 Menu
BasicItemsSourceMenu.ItemsSource = menuItems;
```
**要点:**
- 使用 `TreeDataTemplate` 以支持嵌套子菜单
- `IMenuItemData.Children` 用于定义子菜单树形结构
- 使用 `MenuSeparatorData` 类型的数据项自动生成 `MenuSeparator`
- `MenuItemData` 自动维护 `ParentNode` 父节点引用
---
## 3. 带图标和子菜单
菜单项可以包含 Ant Design 图标。
> 📖 对应 Gallery:`MenuShowCase.axaml` → **"Icon and submenu"** ShowCaseItem
```xml
```
**要点:**
- 使用 `antdicons:AntDesignIconProvider` 标记扩展设置 Ant Design 图标
- 支持多级嵌套子菜单(如 Paste → Paste/Paste from History)
- 图标与文字间距由 `MenuToken.ItemIconMarginInlineEnd` Token 控制
---
## 4. CheckBox / Radio 切换菜单项
菜单项支持 CheckBox 和 Radio 切换交互。
> 📖 对应 Gallery:`MenuShowCase.axaml` → **"menu item with ToggleType"** ShowCaseItem
```xml
```
**要点:**
- `ToggleType="Radio"` + `GroupName` 实现同组互斥选择
- `ToggleType="CheckBox"` 实现独立选中/取消
- 可同时设置图标和 ToggleType
- 通过 `IsCheckStateChanged` 事件监听选中状态变化
### 监听选中变化
```csharp
menuItem.IsCheckStateChanged += (sender, e) =>
{
var item = (MenuItem)sender!;
Console.WriteLine($"{item.Header}: IsChecked = {item.IsChecked}");
};
```
---
## 5. 可滚动菜单
当子菜单项过多时,弹窗会自动出现滚动条。`DisplayPageSize` 控制可见项数量。
> 📖 对应 Gallery:`MenuShowCase.axaml` → **"Scrollable menu"** ShowCaseItem
```xml
```
**要点:**
- 默认 `DisplayPageSize=10`,即弹窗最多显示 10 项,超出后出现滚动条
- 可以通过设置 `DisplayPageSize` 调整可见项数量
---
## 6. 右键上下文菜单(ContextMenu)
通过 `ContextMenu` 属性附加到任意控件,右键点击触发弹出。
> 📖 对应 Gallery:`MenuShowCase.axaml` → **"Context menu"** ShowCaseItem
```xml
```
### 数据驱动的 ContextMenu
> 📖 对应 Gallery:`MenuShowCase.axaml` → **"Context menu, Generate MenuItem by ItemsSource"** ShowCaseItem
```xml
```
---
## 7. MenuFlyout 弹出菜单
`MenuFlyout` 可作为 `ContextFlyout` 使用,通过右键触发弹出。
> 📖 对应 Gallery:`MenuShowCase.axaml` → **"Menu Flyout"** ShowCaseItem
```xml
```
### 数据驱动的 MenuFlyout
```xml
```
---
## 8. 尺寸变体
Menu 支持三种尺寸:`Small`、`Middle`(默认)、`Large`。尺寸影响菜单栏的最小高度、顶层菜单项的内间距和字体大小。
```xml
```
**尺寸影响的 Token 对应关系:**
| SizeType | 最小高度 | 顶层圆角 | 顶层内间距 | 顶层字体 |
|---|---|---|---|---|
| `Large` | `ControlHeightLG` | `TopLevelItemBorderRadiusLG` | `TopLevelItemPaddingLG` | `TopLevelItemFontSizeLG` |
| `Middle` | `ControlHeight` | `TopLevelItemBorderRadius` | `TopLevelItemPadding` | `TopLevelItemFontSize` |
| `Small` | `ControlHeightSM` | `TopLevelItemBorderRadiusSM` | `TopLevelItemPaddingSM` | `TopLevelItemFontSizeSM` |
---
## 9. 动画控制
通过 `IsMotionEnabled` 属性控制子菜单弹出/关闭的动画效果。默认跟随全局 Token `EnableMotion`。
```xml
```
---
## 常见场景
### 应用顶部菜单栏
```xml
```
### 右键上下文菜单 + Command 绑定
```xml
```