MAUI(Android)如何实现带独立上下文菜单且不改变选中项的列表
MAUI Android 实现带独立上下文菜单的单选列表
核心实现思路
放弃之前的SwipeView和ContextFlyout方案,改用Android原生PopupMenu实现任意数量的菜单项,同时通过CollectionView的单选模式+DataTrigger实现选中项高亮,确保菜单操作不干扰选中状态。
1. 定义数据模型与视图模型
首先创建包含必要属性和菜单命令的模型类:
using System.ComponentModel; using System.Runtime.CompilerServices; using Microsoft.Maui.Controls; namespace YourAppNamespace; public class ItemModel : INotifyPropertyChanged { private string _imagePath; public string ImagePath { get => _imagePath; set { _imagePath = value; OnPropertyChanged(); } } private string _name; public string Name { get => _name; set { _name = value; OnPropertyChanged(); } } // 触发菜单的命令 public ICommand ShowMenuCommand { get; set; } public event PropertyChangedEventHandler PropertyChanged; void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
视图模型负责管理列表数据、选中项和菜单逻辑:
using System.Collections.ObjectModel; using System.ComponentModel; using System.Runtime.CompilerServices; using Android.Widget; using Microsoft.Maui.ApplicationModel; using Microsoft.Maui.Controls; namespace YourAppNamespace; public class MainViewModel : INotifyPropertyChanged { public ObservableCollection<ItemModel> Items { get; set; } private ItemModel _selectedItem; public ItemModel SelectedItem { get => _selectedItem; set { _selectedItem = value; OnPropertyChanged(); } } public MainViewModel() { Items = new ObservableCollection<ItemModel>(); // 初始化测试数据 for (int i = 1; i <= 5; i++) { Items.Add(new ItemModel { ImagePath = "sample_image.png", // 替换为你的图片路径 Name = $"列表项 {i}", ShowMenuCommand = new Command<Image>(ShowItemContextMenu) }); } } // 显示原生上下文菜单 void ShowItemContextMenu(Image menuIcon) { if (menuIcon == null) return; var currentActivity = Platform.CurrentActivity; if (currentActivity == null) return; // 创建Android原生PopupMenu var popupMenu = new PopupMenu(currentActivity, menuIcon.Handler.PlatformView as Android.Views.View); // 添加最多10个菜单项 for (int i = 1; i <= 10; i++) { popupMenu.Menu.Add($"菜单选项 {i}"); } // 处理菜单点击事件 popupMenu.MenuItemClick += (s, e) => { Toast.MakeText(currentActivity, $"你选择了:{e.Item.TitleFormatted}", ToastLength.Short).Show(); // 这里可以添加自定义业务逻辑,不会修改SelectedItem }; popupMenu.Show(); } public event PropertyChangedEventHandler PropertyChanged; void OnPropertyChanged([CallerMemberName] string propertyName = null) { PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); } }
2. XAML页面布局
使用CollectionView实现单选列表,通过DataTrigger实现选中项高亮,右侧添加三点图标触发菜单:
<?xml version="1.0" encoding="utf-8" ?> <ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:local="clr-namespace:YourAppNamespace" x:Class="YourAppNamespace.MainPage"> <ContentPage.BindingContext> <local:MainViewModel /> </ContentPage.BindingContext> <CollectionView ItemsSource="{Binding Items}" SelectionMode="Single" SelectedItem="{Binding SelectedItem}" Margin="10"> <CollectionView.ItemTemplate> <DataTemplate> <Grid Padding="12" ColumnDefinitions="Auto,*,Auto"> <!-- 选中项高亮样式 --> <Grid.Style> <Style TargetType="Grid"> <Style.Triggers> <DataTrigger TargetType="Grid" Binding="{Binding Source={RelativeSource AncestorType={x:Type CollectionViewItem}}, Path=IsSelected}" Value="True"> <Setter Property="BackgroundColor" Value="#E5E7EB" /> </DataTrigger> </Style.Triggers> </Style> </Grid.Style> <!-- 显示项图片 --> <Image Source="{Binding ImagePath}" WidthRequest="48" HeightRequest="48" Aspect="AspectFill" CornerRadius="8" /> <!-- 显示项名称 --> <Label Grid.Column="1" Text="{Binding Name}" FontSize="16" VerticalOptions="Center" Margin="16,0" /> <!-- 菜单触发图标 --> <Image Grid.Column="2" Source="dots_menu.png" <!-- 替换为你的三点图标,放入Android项目Resources/drawable --> WidthRequest="24" HeightRequest="24" VerticalOptions="Center"> <Image.GestureRecognizers> <TapGestureRecognizer Command="{Binding ShowMenuCommand}" CommandParameter="{Binding Source={RelativeSource Self}}" /> </Image.GestureRecognizers> </Image> </Grid> </DataTemplate> </CollectionView.ItemTemplate> </CollectionView> </ContentPage>
关键细节说明
- 选中项高亮:通过DataTrigger绑定
CollectionViewItem.IsSelected属性,动态设置Grid背景色,无需额外代码维护选中状态。 - 上下文菜单:直接调用Android原生
PopupMenu,支持显示任意数量的菜单项(这里设置最多10个),避免MAUI内置菜单的兼容性问题。菜单触发通过TapGestureRecognizer绑定命令,传递当前图标控件作为参数,确保菜单显示在正确位置。 - 选中状态不被干扰:菜单操作仅处理自身逻辑,未修改ViewModel的
SelectedItem属性,因此操作菜单不会改变当前选中项。 - Android适配注意:将三点图标
dots_menu.png放入Android项目的Resources/drawable目录,确保资源能正确加载;Platform.CurrentActivity需要MAUI项目已正确初始化,若出现空引用,可在Android项目的MainApplication中添加Microsoft.Maui.ApplicationModel.Platform.Init(this, savedInstanceState);。
内容的提问来源于stack exchange,提问作者Chris Fellows
相关产品推荐
相关产品推荐

