【问题标题】:Getting validateMenuItem: to fire for NSMenuItem using Xamarin-generated action获取 validateMenuItem:使用 Xamarin 生成的操作触发 NSMenuItem
【发布时间】:2023-03-22 05:15:01
【问题描述】:

我想在我的上下文菜单中添加其他菜单项。理想情况下,使用 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:没有被调用。使用此方法分配的动作是 __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);
    }

现在如果我能找到调用原始事件的方法!

【问题讨论】:

    标签: c# xcode cocoa xamarin xamarin.mac


    【解决方案1】:

    此问题是 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-03
      • 1970-01-01
      • 2017-09-01
      相关资源
      最近更新 更多