如何在MAUI.NET控件中添加而非重定义上下文菜单项
在.NET MAUI Entry控件中添加自定义上下文菜单项而不覆盖默认菜单
问题描述
我按照官方教程给Entry控件实现了上下文菜单,代码如下:
<Entry ...> <FlyoutBase.ContextFlyout> <MenuFlyout> <MenuFlyoutItem Text="..." Command="..." CommandParameter="..." /> </MenuFlyout> </FlyoutBase.ContextFlyout> </Entry>
菜单能正常工作,但Entry自带的复制、粘贴等默认上下文菜单项被完全覆盖了。想找一个无需重写默认行为的简便方法,把自定义菜单项插入到默认菜单列表中。
解决方案
方法1:通过平台特定渲染器扩展默认菜单
Entry的默认上下文菜单由各平台原生控件提供,直接替换ContextFlyout会覆盖原生菜单,因此需要通过平台特定代码获取原生菜单并追加自定义项:
Android平台实现
在Android项目中创建自定义Entry渲染器:
using Android.Content; using Android.Views; using Microsoft.Maui.Controls.Platform; [assembly: ExportRenderer(typeof(Entry), typeof(CustomEntryRenderer))] namespace YourAppNamespace.Droid { public class CustomEntryRenderer : EntryRenderer { public CustomEntryRenderer(Context context) : base(context) { } protected override void OnElementChanged(ElementChangedEventArgs<Entry> e) { base.OnElementChanged(e); if (Control != null) { Control.CustomSelectionActionModeCallback = new CustomActionCallback(Control); } } private class CustomActionCallback : Java.Lang.Object, ActionMode.ICallback { private readonly Android.Widget.EditText _editText; public CustomActionCallback(Android.Widget.EditText editText) { _editText = editText; } public bool OnCreateActionMode(ActionMode mode, IMenu menu) { // 保留默认菜单项 _editText.CreateActionMode(mode, menu); // 追加自定义菜单项 var customItem = menu.Add("自定义操作"); customItem.SetOnMenuItemClickListener(new CustomMenuItemClickListener(_editText, mode)); return true; } public bool OnPrepareActionMode(ActionMode mode, IMenu menu) => false; public bool OnActionItemClicked(ActionMode mode, IMenuItem item) { if (item.TitleFormatted.ToString() == "自定义操作") { // 执行自定义逻辑,可绑定ViewModel命令 var entry = _editText.Tag as Entry; (entry.BindingContext as YourViewModel)?.CustomCommand.Execute(null); mode.Finish(); return true; } return false; } public void OnDestroyActionMode(ActionMode mode) { } } private class CustomMenuItemClickListener : Java.Lang.Object, IMenuItemOnMenuItemClickListener { private readonly Android.Widget.EditText _editText; private readonly ActionMode _actionMode; public CustomMenuItemClickListener(Android.Widget.EditText editText, ActionMode actionMode) { _editText = editText; _actionMode = actionMode; } public bool OnMenuItemClick(IMenuItem item) => true; } } }
iOS平台实现
在iOS项目中创建自定义Entry渲染器:
using UIKit; using Microsoft.Maui.Controls.Platform; [assembly: ExportRenderer(typeof(Entry), typeof(CustomEntryRenderer))] namespace YourAppNamespace.iOS { public class CustomEntryRenderer : EntryRenderer { protected override void OnElementChanged(ElementChangedEventArgs<Entry> e) { base.OnElementChanged(e); if (Control != null) { Control.ShouldShowMenu = (textField) => { // 获取默认菜单并追加自定义项 var defaultMenu = textField.ShouldShowMenu(); if (defaultMenu != null) { var customItem = new UIMenuItem("自定义操作", new ObjCRuntime.Selector("HandleCustomAction:")); defaultMenu.AddItem(customItem); } return true; }; // 绑定自定义操作的处理方法 Control.AddTarget(HandleCustomAction, UIControlEvent.MenuActionTriggered, new ObjCRuntime.Selector("HandleCustomAction:")); } } [ObjCRuntime.Export("HandleCustomAction:")] void HandleCustomAction(UIMenuItem sender) { // 执行自定义逻辑,可绑定ViewModel命令 var entry = Element as Entry; (entry.BindingContext as YourViewModel)?.CustomCommand.Execute(null); } } }
方法2:利用MAUI Community Toolkit扩展
如果项目已引入MAUI Community Toolkit,可以使用其提供的上下文菜单扩展方法,直接在默认菜单基础上追加自定义项,无需编写原生渲染器代码(需注意版本兼容性)。
内容的提问来源于stack exchange,提问作者jaydopartu
相关产品推荐
相关产品推荐

