views:

1509

answers:

1

I was wondering if SO could help simplify some logic. I have a windows form (C# 2.0) which contains a System.Windows.Forms.MenuStrip.

  1. I want to dynamically add ToolStripMenueItems to the MenuStrip. The added items will be driven off of a database (but for simplicity I have removed that part from the code below).
  2. I would like to be able to build complex menus (i.e Tools>Math>Calc, Help>Documents, Help>About, Format>Encoding>Western, Format>Encoding>Other>Greek).

The code below seems to work but what would you do to make loadToolbars() more efficient/simpler?

This is the function I need help with:

void loadToolbars()
{
    foreach(Toolbar t in getToolStripItems())
    {
        string[] toolPath = t.toolbar.Split(">".ToCharArray(),StringSplitOptions.RemoveEmptyEntries);
        ToolStripMenuItem root = null;
        ToolStripItem[] foundItems;

        /*
         * follow the path of each Toolbar item.  If we find a dead-end,
         * add the missing part
         */
        for(int i=0; i<toolPath.Length; i++)
        {
            if(root == null)
            {
                //Search the main menu strip (System.Windows.Forms.MenuStrip)
                foundItems = DA_Menu.Items.Find(toolPath[i],false);
            }else
            {
                //Continue searching were we left off
                foundItems = root.DropDownItems.Find(toolPath[i],false);
            }

            if(foundItems.Length>0)
            {
                foreach(ToolStripItem item in foundItems)
                {
                    //Is this the Toolbar item I am looking for?
                    if(item.Text == toolPath[i])
                    {
                        if(item.OwnerItem != null && i>0)
                        {
                            if((item.OwnerItem.Text == toolPath[i-1]) 
                                && (item.Text == toolPath[i]))
                                root = (ToolStripMenuItem)item;
                        }else
                        {
                            root = (ToolStripMenuItem)item;
                        }
                    }
                }
            }else
            {
                //We hit a dead-end.  Add the missing path
                if(root == null)
                {
                    root = new ToolStripMenuItem(toolPath[i]);
                    root.Name = toolPath[i];
                    DA_Menu.Items.Add(root);
                }else
                {
                    ToolStripMenuItem tsmi = new ToolStripMenuItem(toolPath[i]);
                    tsmi.Name = toolPath[i];
                    root.DropDownItems.Add(tsmi);
                    root = tsmi;
                }
            }
        }

        //Add the Toobar item to the path that was built above
        t.Click +=new EventHandler(Toolbar_Click);
        ((ToolStripMenuItem)root).DropDownItems.Add(t);
    }
}

Everthing below, I am happy with but I am providing it to help others follow what I am doing.

This function is data driven but hard coded for the benefit of SO

private List<Toolbar> getToolStripItems()
{
   List<Toolbar>toolbars = new List<Toolbar>();

   Toolbar t = new Toolbar();
   t.Text = "Calc";
   t.path = "c:\windows\system32\calc.exe";
   t.toolbar = "Tools>Microsoft>Math";

   toolbars.Add(t);

   t = new Toolbar()
   t.Text = "Calc2";
   t.path = "c:\windows\system32\calc.exe";
   t.toolbar = "Tools>Math>Microsoft";

   toolbars.Add(t);

   return toolbars;
}

Custom class to help keep my click events simple

class Toolbar:ToolStripMenuItem
{
    public string path;
    public string toolbar;
    public Toolbar()
    {
        /*
         * Set the name to the Text value
         * so that it can be found in collection
         * by key
         */
        base.Name = Text;
    }
}

All Toolbar item Click events will be handled in this function

void Toolbar_Click(object sender, EventArgs e)
{
    //Get the Toolbar item that was clicked
    Toolbar t = (Toolbar)sender;

    //Start new process
    System.Diagnostics.Process p = new System.Diagnostics.Process();
    p.StartInfo.FileName = t.path;
    p.Start();
}
+1  A: 

The problem is the form that your data is in. If you stick to that form I don't think there is much to do.

Otherwise change your data from a flat field structure like "Tools>Microsoft>Math" to something like a TreeList e.g. a Tools list including a Microsoft list including a Math list including your app entries. You could even build that structure in the database.

Then you can easily add the menu items recursively.

Foxfire
Thanks for your feedback. That is not a bad idea. I may consider using an xml config file to create a treelist like structure and dropping the database all together... I will play around with it and see how I like. Gave you +1 for quick good response.
J.Hendrix