Click here to Skip to main content
15,890,557 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
Hi I am trying to create dynamic menu on mouse click, I am able to create Parent menu and Child menu, but I am not able to create subChlid menu. Only the last subChild menu i.e. "OutPut 6" is visible.
I am new to C# and I refer Code Project for help. Is this happening because there is only one instance of subChild. But I don't want to create multiple instance of subChild. All Suggestions are welcome.

C#
void lstView_MouseClick(object sender, MouseEventArgs e)
{
    //throw new NotImplementedException();
    switch(e.Button)
    {
        case System.Windows.Forms.MouseButtons.Right:

            MenuItem[] subChild = new MenuItem[3];
            subChild[0] = new MenuItem("Digital", IO_Click);
            subChild[1] = new MenuItem("Analog", IO_Click);
            subChild[2] = new MenuItem("Special", IO_Click);

            MenuItem[] parent = new MenuItem[2];
            parent[0] = new MenuItem("InPut", IO_Click);
            parent[1] = new MenuItem("OutPut", IO_Click);

            MenuItem[] ipChild = new MenuItem[9];
            for (int ip = 0; ip < 9; ip++)
            {
                ipChild[ip] = new MenuItem("Input " + (ip + 1).ToString(), IO_Click);
                ipChild[ip].MenuItems.Add(subChild[0]);
                ipChild[ip].MenuItems.Add(subChild[1]);
                ipChild[ip].MenuItems.Add(subChild[2]);
                parent[0].MenuItems.Add(ipChild[ip]);
            }

            MenuItem[] opChild = new MenuItem[6];
            for (int op = 0; op < 6; op++)
            {
                opChild[op] = new MenuItem("Output " + (op + 1).ToString(), IO_Click);
                opChild[op].MenuItems.Add(subChild[0]);
                opChild[op].MenuItems.Add(subChild[1]);
                opChild[op].MenuItems.Add(subChild[2]);
                parent[1].MenuItems.Add(opChild[op]);
            }
            /* List View for Menu in List View */
            lstViewMenu = new ContextMenu(parent);
            lstViewMenu.Show(lstView, e.Location);

            break;
        default:
            break;
    }
}
Posted

1 solution

I believe it's because MenuItem can only belong to one single parent MenuItem (though I'm not 100% positive - MSDN doesn't mention anything about that in http://msdn.microsoft.com/en-us//library/system.windows.forms.menuitem%28v=vs.110%29.aspx[^], so it requires disassembling to be sure). But since it has Parent property, which refers to the parent menu item, I think it's true. If menu item can only have single parent, it means every time you add this menu item to another menu, the said item is "detached" from the parent it previously belonged to.
So, to fix your issue, I'd propose one of the following:
1) Put
C#
MenuItem[] subChild = new MenuItem[3];
subChild[0] = new MenuItem("Digital", IO_Click);
subChild[1] = new MenuItem("Analog", IO_Click);
subChild[2] = new MenuItem("Special", IO_Click);

block in both of the cycles for opChild and inChild:



2) Use CloneMenu() method which creates a duplicate of the current object, e.g.
C#
ipChild[ip].MenuItems.Add(subChild[0].CloneMenu());


UPD: I discovered that MSDN actually mentions this restrinction in CloneMenu() method description: MenuItem objects cannot be used in more than one place unless you obtain a copy of the MenuItem. Also, since CloneMenu() performs a deep copying (i.e. also creates a copy of all the submenus), I propose the following code with less arrays:

case System.Windows.Forms.MouseButtons.Right:

C#
            case System.Windows.Forms.MouseButtons.Right:

    MenuItem pTypeSubmenu = new MenuItem(string.Empty, IO_Click);

    pTypeSubmenu.MenuItems.Add(new MenuItem("Digital", IO_Click));
    pTypeSubmenu.MenuItems.Add(new MenuItem("Analog", IO_Click));
    pTypeSubmenu.MenuItems.Add(new MenuItem("Special", IO_Click));

    MenuItem[] parent = new MenuItem[2];
    parent[0] = new MenuItem("InPut", IO_Click);
    parent[1] = new MenuItem("OutPut", IO_Click);

    MenuItem pSubmenu = null;
    for (int ip = 0; ip < 9; ip++)
    {
        pSubmenu = pTypeSubmenu.CloneMenu();
        pSubmenu.Text = "Input " + (ip + 1).ToString();
        parent[0].MenuItems.Add(pSubmenu);
    }

    for (int op = 0; op < 6; op++)
    {
        pSubmenu = pTypeSubmenu.CloneMenu();
        pSubmenu.Text = "Output " + (op + 1).ToString();
        parent[1].MenuItems.Add(pSubmenu);
    }
    /* List View for Menu in List View */
    lstViewMenu = new ContextMenu(parent);
    lstViewMenu.Show(lstView, e.Location);

    break;
default:
    break;
 
Share this answer
 
v3
Comments
thechauvinism 17-Jun-14 6:53am    
Thanks @Timberbird that was quick and easy.
Timberbird 17-Jun-14 7:38am    
You're welcome! (and pardon my English) I've updated the solution proposing slightly modified implementation based on CloneMenu() method

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900