我想在我的上下文菜单中添加其他菜单项。理想情况下,使用validateMenuItem启用项目:
[Action("validateMenuItem:")]
public bool ValidateMenuItem(NSMenuItem item)
{
_logger.DebugFormat("Validating {0} menu item with Action {1}", item.Title, item.Action.Name);
var target = item.Target;
var menuItem = ViewModel.ContextMenu.Where(x => x.Title == item.Title).FirstOrDefault();
if (menuItem != null) {
return menuItem.Command.CanExecute();
}
return false;
}
每https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/MenuList/Articles/EnablingMenuItems.html。如果我手动创建一个动作,则会调用它,但是如果我像这样分配一个事件处理程序:
var nsMenuItem = new NSMenuItem(menuItem.Title,
(sender, e) =>
{
menuItem.Command.ExecuteAsync();
});
nsMenuItem.Target = this;
validateMenuItem:不会被调用。使用此方法分配的Action是__monomac_internal_ActionDispatcher_activated:来自https://github.com/xamarin/xamarin-macios/blob/master/src/AppKit/ActionDispatcher.cs(请帮助我Rolf Bjarne Kvinge)。由于我的课程中没有这个动作(我认为),所以从不调用validateMenuItem,我的菜单项永远不会被激活。我怎样才能做到这一点?
更新。如果我将其添加到我的视图控制器,
[Action("__monomac_internal_ActionDispatcher_activated:")]
public void MonomacInternalAction(NSObject sender)
{
}
validateMenuItem:调用新项目。但是,事件处理程序将替换为此函数。 (这个问题可能无法解决!)这可能是导出与动作问题 - 我看到了
const string skey = "__monomac_internal_ActionDispatcher_activated:";
[Preserve, Export (skey)]
public void OnActivated (NSObject sender)
{
EventHandler handler = Activated;
if (handler != null)
handler (sender, EventArgs.Empty);
}
更新2。刚刚找到https://bugzilla.xamarin.com/show_bug.cgi?id=51343
更新3。我可以使用
欺骗validateMenuItem public override bool RespondsToSelector(ObjCRuntime.Selector sel)
{
if (sel.Name.Contains("__monomac_internal_ActionDispatcher_activated")) {
return true;
}
return base.RespondsToSelector(sel);
}
现在,如果我只能找到一种调用原始事件的方法!
答案 0 :(得分:0)
此问题是Xamarin.Mac实施中的错误 - https://bugzilla.xamarin.com/show_bug.cgi?id=51343。我最终得到了一个解决方法。我没有为每个菜单项使用事件处理程序或单独的操作(无法确定如何注册),而是创建了一个处理所有菜单项的操作。
[Action("contextAction:")]
public void contextAction(NSObject sender)
{
if (sender is NSMenuItem)
{
var nsMenuItem = (NSMenuItem)sender;
var wrapper = nsMenuItem.RepresentedObject as NSObjectWrapper;
if (wrapper != null) {
var menuItem = wrapper.Context as MenuItem;
if (menuItem != null) {
menuItem.Command.ExecuteAsync();
}
}
}
}
然后
foreach (var menuItem in ViewModel.ContextMenu)
{
var selector = new ObjCRuntime.Selector("contextAction:");
var nsMenuItem = new NSMenuItem(menuItem.Title, selector, "");
nsMenuItem.RepresentedObject = new NSObjectWrapper(menuItem);
NSObjectWrapper来自Monotouch: convert an Object to NSObject。