2

I have a form which contains tab panel with many tap pages. Each of them has its own context menu (display on right-click). But If I add a ToolStripMenuItem to multiple ContextMenuStrips only last menu strip really has this menu item. Simple code example is:

    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;

If one shows this menus one by one, first will be empty...How can I achieve what I want?

sll
  • 61,540
  • 22
  • 104
  • 156
Tadeusz
  • 6,453
  • 9
  • 40
  • 58

2 Answers2

1

one context menu is displayed once at a time; you probably don't need many clones everywhere, but you may want to move one single instance of your menu items to the menu menu strip at the moment menu strip is opening;

I'm moving here the named (grand) parent's items to the child (currently opening) menu when the local copy is empty, and all the next ctx openings I just AddRange, which moves the "located" three menu items from the previously opened ctxMenuStrip to the currently-opening-one:

    // 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();
    }
1

Thi is because visual can not be child of multiple diferent visuals in the same time. In your case tim_refresh is a child of cms1 and cms2 at the same time.

You need to create two completely separate instances of ToolStripMenuItem.

EDIT:

You can extract visual creation in factor method to simplify multiple objects instantiation:

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"));
sll
  • 61,540
  • 22
  • 104
  • 156
  • Mm, Is there any simple way to do many copies of one menuitem? – Tadeusz Nov 29 '11 at 09:00
  • Clone it, see my SO post with DeepCopy sources [Is there a much better way to create deep and shallow clones in C#](http://stackoverflow.com/a/8025905/485076). So you need copy MemoryUtils class in your project then for any object in your soluwion you would be able call DeepCopy() method (it is extension method, I believe you know what is it) – sll Nov 29 '11 at 09:03
  • Considering that object you need to create is pretty simpel I would suggest not using clone for this and just instantiate explicitly how many you need instances, see EDIT part of my question, just use this method to create two instances – sll Nov 29 '11 at 09:16