【问题标题】:ToolStripMenuItem for multiple ContextMenuStripToolStripMenuItem 用于多个 ContextMenuStrip
【发布时间】:2012-01-08 15:03:19
【问题描述】:

我有一个表单,其中包含带有许多点击页面的标签面板。它们中的每一个都有自己的上下文菜单(右键单击时显示)。但是如果我将 ToolStripMenuItem 添加到多个 ContextMenuStrips 只有最后一个菜单条真正有这个菜单项。 简单的代码示例是:

    ToolStripMenuItem tim_refresh = new ToolStripMenuItem("Refresh", null, (o, e) =>
        {
            MessageBox.Show("Refresh");
        });

    ContextMenuStrip cms1 = new ContextMenuStrip();
    cms1.Items.Add(tim_refresh);

    ContextMenuStrip cms2 = new ContextMenuStrip();
    cms2.Items.Add(tim_refresh);

    this.tblDataManagerObjects.ContextMenuStrip = cms1;
    this.tblDataSourceTypes.ContextMenuStrip = cms2;

如果一个一个地显示这个菜单,第一个会是空的……我怎样才能达到我想要的?

【问题讨论】:

    标签: c# .net wpf contextmenu contextmenustrip


    【解决方案1】:

    一次显示一个上下文菜单;您可能不需要到处克隆很多副本,但您可能希望在打开菜单条时将单个菜单项实例移动到菜单条;

    当本地副本为空时,我将这里命名的(大)父项的项目移动到子(当前打开的)菜单,并且所有下一个 ctx 开口我只是 AddRange,它将“定位”的三个菜单项从中移动之前打开的 ctxMenuStrip 到当前打开的:

        // http://stackoverflow.com/questions/8307959/toolstripmenuitem-for-multiple-contextmenustrip?rq=1
        // http://stackoverflow.com/questions/6275120/toolstripmenuitem-added-to-several-places?rq=1
        // WILL_ADD_PARENT_MENU_ITEMS_IN_Opening first time opened we locate common menu items from GrandParent, then we move them to the current slider; cool?
        private static ToolStripItem[] separatorLoadSave = null;
        private void contextMenuStrip1_Opening(object sender, CancelEventArgs e) {
            if (separatorLoadSave == null) {
                separatorLoadSave = new ToolStripItem[3];
    
                Control slidersAutoGrow = base.Parent;
                if (base.Parent.Name != "SlidersAutoGrow") return;
                Control slidersForm = slidersAutoGrow.Parent;
                if (slidersForm.Name != "SlidersForm") return;
    
                ToolStripItem[] separator = slidersForm.ContextMenuStrip.Items.Find("toolStripSeparator1", false);
                if (separator.Length > 0) separatorLoadSave[0] = separator[0];
    
                ToolStripItem[] load = slidersForm.ContextMenuStrip.Items.Find("mniParameterSetLoad", false);
                if (load.Length > 0) separatorLoadSave[1] = load[0];
    
                ToolStripItem[] save = slidersForm.ContextMenuStrip.Items.Find("mniParameterSetSave", false);
                if (save.Length > 0) separatorLoadSave[2] = save[0];
            }
    
            this.contextMenuStrip1.SuspendLayout();
            this.contextMenuStrip1.Items.AddRange(separatorLoadSave);
            this.contextMenuStrip1.ResumeLayout();
        }
    

    【讨论】:

      【解决方案2】:

      这是因为视觉不能同时是多个不同视觉的子级。在您的情况下,tim_refresh 同时是 cms1cms2 的孩子。

      您需要创建两个完全独立的 ToolStripMenuItem 实例。

      编辑:

      您可以在因子方法中提取视觉创建以简化多个对象的实例化:

      private ToolStripMenuItem CreateToolStripMenuItem(string name)
      {
         return new ToolStripMenuItem(name, null, (o, e) =>
              {
                  MessageBox.Show(name);
              });
      }
      
      // then just call it once per each menu strip
      ContextMenuStrip cms1 = new ContextMenuStrip();
      cms1.Items.Add(CreateToolStripMenuItem("Refresh"));
      
      ContextMenuStrip cms2 = new ContextMenuStrip();
      cms2.Items.Add(CreateToolStripMenuItem("Refresh"));
      

      【讨论】:

      • 嗯,有没有什么简单的方法可以复制一份菜单项?
      • 克隆它,请参阅我的 SO 帖子,其中包含 DeepCopy 源 Is there a much better way to create deep and shallow clones in C#。因此,您需要在项目中复制 MemoryUtils 类,然后对于解决方案中的任何对象,您都可以调用 DeepCopy() 方法(它是扩展方法,我相信您知道它是什么)
      • 考虑到您需要创建的对象非常简单,我建议不要为此使用克隆,只需明确实例化您需要多少个实例,请参阅我的问题的编辑部分,只需使用此方法创建两个实例
      猜你喜欢
      • 2011-09-13
      • 2013-11-28
      • 2014-03-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-19
      • 2011-08-07
      相关资源
      最近更新 更多