【问题标题】:.NET MenuItem.IsSubmenuOpen = true only works the first time.NET MenuItem.IsSubmenuOpen = true 仅在第一次工作
【发布时间】:2012-01-04 09:03:44
【问题描述】:

我有一个 ContextMenu,其中包含一些可以选择的项目 (MenuItem) 的子菜单。打开 ContextMenu 时,我想递归地打开当前选中的项目。所以,我有以下代码:

    protected override void OnOpened( RoutedEventArgs e ) {
        base.OnOpened( e );
        OpenCurrentSubMenu( Items );
    }

    private static bool OpenCurrentSubMenu( ItemCollection itemCollection ) {
        foreach (MenuItem item in itemCollection) {
            if (item.IsChecked) {
                return true;
            }
            else if( OpenCurrentSubMenu( item.Items ) ) {
                item.IsSubmenuOpen = true;
                return true;
            }
        }
        return false;
    }

我还有一些其他代码可以确保只检查一项。

当我第一次在子菜单中选择一个项目时,这似乎很有效。当我重新打开 ContextMenu 时,打开的子菜单级联打开到所选项目:

但是,当我离开上下文菜单并再次打开它时,所选菜单不会打开:

有谁知道为什么以及如何解决它?

【问题讨论】:

  • 您的标题显示“IsItemChecked”,但您的代码显示“IsSubmenuOpen”。
  • @ScottRippey - 已更新。谢谢。
  • 你能用更多级别的菜单来测试这个吗?每次重新打开都会减少 1 级重新打开,还是总是不打开最终菜单?
  • @Damien_The_Unbeliever - 经过一些实验,似乎在进行选择后的第一个 Open 可以工作到 n 个级别。但是,下一个和后面的 Open 只打开到 1 级。

标签: c# .net contextmenu submenu


【解决方案1】:

没有一个解决方案对我有效/清晰,而且没有一个看起来很优雅。 我发现了一些有用的东西。

试试这个:

    public partial class WindowWithContextMenu : Window
    {

        // Add this Show method
        public new void Show()
        {
            base.Show();
            base.Activate();

            // Do this for any context menu!
            MyContextMenu.IsSubmenuOpen = true;
            MyContextMenu.IsSubmenuOpen = false;

            MyContextMenu2.IsSubmenuOpen = true;
            MyContextMenu2.IsSubmenuOpen = false;

            // And so on
        }

        ... 
        ...

    }

这样你就可以稍微修改一下原来窗口的Show() 方法。 现在,当您调用 Show() 方法时,它将运行这个小技巧。

然后在某个时候,您可能会单击打开菜单的某个按钮。 问题是,这一次它将永远有效,而不仅仅是第一次!

MyContextMenuMyContextMenu2 在 XAML 文件中定义,默认情况下不会在 XAML 文件中打开。

我不知道为什么会这样,但确实如此。它很丑,但破解很简单,而且是一种复制粘贴的解决方案......

我还发现,为了重现问题,您需要锁定帐户并重新登录。每次我这样做时,它都会 100% 复制。

【讨论】:

    【解决方案2】:

    尝试三件事:

    • 打开上下文菜单时,在整个层次结构中递归并设置 IsSubmenuOpen = false,然后再尝试打开任何子菜单。可能是之前打开的子菜单被记住了,因此您试图告诉它在同一级别有两个打开的子菜单。

    • 递归查找需要打开的子菜单并将它们存储在列表中。然后遍历列表并设置它们,以便在其子子菜单设置为打开之前将最顶层的菜单设置为打开。 (可能是在父级尚未打开时尝试打开子级并不总是可靠的)。

    • 讨厌的蛮力方法:每次打开上下文菜单时删除并重新创建它。这不好,但如果您打开上下文菜单,您可能会担心性能影响。而且好像第一次就成功了,所以每次都是第一次。

    【讨论】:

    • 好建议。我尝试了几种变体:我尝试了 Scott Rippey 的方法。我还尝试在关闭时设置 IsSubmenuOpen = false,但无济于事。您的第二个项目符号很有趣,但没有解释为什么第一次级联起作用,但以下几次都没有。蛮力总是一种选择:)
    • 似乎第二个选项可以解决问题,尽管它仍然没有解释为什么级联第一次起作用。 !@*$# MS .NET
    • 某些信息可能在第一次尝试时未缓存,因此无论您设置菜单打开的顺序如何,它都可以工作,但在随后的尝试中,菜单系统“更了解”现有的层次结构或状态菜单项,因此会因您尝试更改内容而感到困惑。
    【解决方案3】:

    我认为逻辑应该很好......当检查菜单项时,而不是检查子菜单项时。 在我看来,尝试两个循环....一个用于菜单,另一个用于子菜单项。

    【讨论】:

      【解决方案4】:

      在将其设置回 true 之前,将值设置为 false 可能会有所帮助。不过我无法确认。

      item.IsSubmenuOpen = false;
      item.IsSubmenuOpen = true;
      

      【讨论】:

      • 感谢您的提示,斯科特。我以前见过类似的 .NET 问题解决方案,而且看起来很有希望。不幸的是,在这种情况下它不起作用。
      猜你喜欢
      • 1970-01-01
      • 2016-02-17
      • 2017-09-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-06
      相关资源
      最近更新 更多