如何在.NET MAUI桌面应用中用C# Markup实现带条件的菜单栏
用C# Markup实现.NET MAUI菜单栏并添加条件显示控制
1. 准备工作
确保项目已安装Microsoft.Maui.Controls.Markup NuGet包,这是使用C# Markup语法的核心依赖。
2. 基础菜单栏实现(对应原XAML结构)
在ContentPage的构造函数中,用C# Markup链式语法还原原XAML的菜单栏结构:
using Microsoft.Maui.Controls.Markup; public class YourPage : ContentPage { private readonly YourViewModel _viewModel; public YourPage() { _viewModel = new YourViewModel(); BindingContext = _viewModel; // 构建菜单栏 MenuBarItems( // File菜单 new MenuBarItem("File") .Add(new MenuFlyoutItem("Exit") .Bind(MenuFlyoutItem.CommandProperty, nameof(YourViewModel.ExitCommand))), // Locations菜单 new MenuBarItem("Locations") // Change Location子菜单 .Add(new MenuFlyoutSubItem("Change Location") .Add( new MenuFlyoutItem("Redmond, USA") .Bind(MenuFlyoutItem.CommandProperty, nameof(YourViewModel.ChangeLocationCommand)) .Bind(MenuFlyoutItem.CommandParameterProperty, "Redmond"), new MenuFlyoutItem("London, UK") .Bind(MenuFlyoutItem.CommandProperty, nameof(YourViewModel.ChangeLocationCommand)) .Bind(MenuFlyoutItem.CommandParameterProperty, "London"), new MenuFlyoutItem("Berlin, DE") .Bind(MenuFlyoutItem.CommandProperty, nameof(YourViewModel.ChangeLocationCommand)) .Bind(MenuFlyoutItem.CommandParameterProperty, "Berlin") )) .Add(new MenuFlyoutSeparator()) ); } }
3. 添加条件显示控制
根据场景不同,有三种常用的条件控制方式:
方式一:静态条件判断(初始化时决定是否添加)
适合无需动态变化的场景(如权限检查),使用C# Markup提供的AddIf扩展方法:
// 在Locations菜单的分隔线后添加以下代码 .AddIf(HasAddLocationPermission(), // 自定义权限检查逻辑 new MenuFlyoutItem("Add Location") .Bind(MenuFlyoutItem.CommandProperty, nameof(YourViewModel.AddLocationCommand)))
自定义权限检查方法示例:
private bool HasAddLocationPermission() { // 这里编写实际权限判断逻辑,比如检查用户角色 return _viewModel.CurrentUser.HasPermission(Permissions.AddLocation); }
方式二:动态绑定IsVisible(实时响应属性变化)
适合需要根据ViewModel属性动态切换显示状态的场景(如选中位置后才显示"Edit Location"):
// 在Add Location项后添加 .Add(new MenuFlyoutItem("Edit Location") .Bind(MenuFlyoutItem.CommandProperty, nameof(YourViewModel.EditLocationCommand)) .Bind(VisualElement.IsVisibleProperty, nameof(YourViewModel.IsLocationSelected)))
对应的ViewModel需包含实现INotifyPropertyChanged的属性:
public class YourViewModel : INotifyPropertyChanged { private bool _isLocationSelected; public bool IsLocationSelected { get => _isLocationSelected; set { _isLocationSelected = value; OnPropertyChanged(); } } // 其他命令定义 public ICommand EditLocationCommand { get; } public event PropertyChangedEventHandler PropertyChanged; protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
方式三:动态条件添加(基于实时状态)
如果需要在菜单每次打开时重新判断是否添加项,使用AddIf的委托重载:
.AddIf(() => _viewModel.IsLocationSelected, new MenuFlyoutItem("Remove Location") .Bind(MenuFlyoutItem.CommandProperty, nameof(YourViewModel.RemoveLocationCommand)))
完整整合代码
将所有逻辑整合后的构造函数代码:
public YourPage() { _viewModel = new YourViewModel(); BindingContext = _viewModel; MenuBarItems( new MenuBarItem("File") .Add(new MenuFlyoutItem("Exit") .Bind(MenuFlyoutItem.CommandProperty, nameof(YourViewModel.ExitCommand))), new MenuBarItem("Locations") .Add(new MenuFlyoutSubItem("Change Location") .Add( new MenuFlyoutItem("Redmond, USA") .Bind(MenuFlyoutItem.CommandProperty, nameof(YourViewModel.ChangeLocationCommand)) .Bind(MenuFlyoutItem.CommandParameterProperty, "Redmond"), new MenuFlyoutItem("London, UK") .Bind(MenuFlyoutItem.CommandProperty, nameof(YourViewModel.ChangeLocationCommand)) .Bind(MenuFlyoutItem.CommandParameterProperty, "London"), new MenuFlyoutItem("Berlin, DE") .Bind(MenuFlyoutItem.CommandProperty, nameof(YourViewModel.ChangeLocationCommand)) .Bind(MenuFlyoutItem.CommandParameterProperty, "Berlin") )) .Add(new MenuFlyoutSeparator()) .AddIf(HasAddLocationPermission(), new MenuFlyoutItem("Add Location") .Bind(MenuFlyoutItem.CommandProperty, nameof(YourViewModel.AddLocationCommand))) .Add(new MenuFlyoutItem("Edit Location") .Bind(MenuFlyoutItem.CommandProperty, nameof(YourViewModel.EditLocationCommand)) .Bind(VisualElement.IsVisibleProperty, nameof(YourViewModel.IsLocationSelected))) .AddIf(() => _viewModel.IsLocationSelected, new MenuFlyoutItem("Remove Location") .Bind(MenuFlyoutItem.CommandProperty, nameof(YourViewModel.RemoveLocationCommand))) ); }
内容的提问来源于stack exchange,提问作者Le Anh Xuan
相关产品推荐
相关产品推荐

