As the OP has tried Solution 1 and is having some problems here's my twopennorth...
I created a Windows Forms application in VB.NET where the only control on the Form is an "empty" MenuStrip - i.e. no menu items added via the Designer
I decided to hold my Menu definitions in an XML document ... the style of XML lends itself nicely to a menu structure and an XML document can be populated in a variety of ways. For the purposes of this example I just stored the data in a text document which I just load
Private Function GetMenus() As XmlDocument
Dim xxml As XmlDocument = New XmlDocument()
xxml.Load("c:\\temp\\SampleData.xml")
Return xxml
End Function
This is the XML I used - I hope I've explained it well enough
="1.0"="UTF-8"
<Menus>
<TopLevel text="Menu 1">
<NextLevel text="Menu 1.A">Menu1A</NextLevel>
<NextLevel text="Menu 1.B">Menu1B</NextLevel>
<NextLevel text="Menu 1.C">Menu1C</NextLevel>
</TopLevel>
<TopLevel text="Menu 2">Menu2</TopLevel>
<TopLevel text="Menu 3">
<NextLevel text="Menu 3.A">Menu3A</NextLevel>
<NextLevel text="Menu 3.B">Menu3B</NextLevel>
</TopLevel>
</Menus>
Which represents a menu structure like this
Menu 1 Menu 2 Menu 3
Menu 1.A Menu 3.A
Menu 1.B Menu 3.B
Menu 1.C
In the link in Solution 1 the Author has used a nice trick to determine which Form to load. I've opted to use Reflection to work out which function to call.
The key is to have all of the routines that could be called from the menus in a simple class.
Here's the one I used
Public Class DynamicMenuSubs
Public Sub Menu1A()
Debug.Print("Called Menu1A")
End Sub
Public Sub Menu1B()
Debug.Print("Called Menu1B")
End Sub
Public Sub Menu1C()
Debug.Print("Called Menu1C")
End Sub
Public Sub Menu2()
Debug.Print("Called Menu2")
End Sub
Public Sub Menu3A()
Debug.Print("Called Menu3A")
End Sub
Public Sub Menu3B()
Debug.Print("Called Menu3B")
End Sub
End Class
Note that the Sub names match (exactly) to the InnerText in the XML above.
Because I only want to visit the database (or XML) once I decided to store the name of the function to call as the Tag of each MenuItem, so here is my code for creating the menus
Private Sub BuildMenus()
Dim xxml As XmlDocument = GetMenus()
Dim toplevels As XmlNodeList = xxml.SelectNodes("Menus/TopLevel")
Dim node As XmlNode
'Top level menus
For Each node In toplevels
Dim tsmi As New ToolStripMenuItem
tsmi.Text = node.Attributes("text").Value
Dim sublevels As XmlNodeList = node.SelectNodes("NextLevel")
If sublevels.Count = 0 Then
'No sub-menus therefore set the tag of this menuitem to the function name
tsmi.Tag = node.InnerText
AddHandler tsmi.Click, AddressOf DynamicMenuHandler
Else
Dim subnode As XmlNode
For Each subnode In sublevels
Dim ddi As New ToolStripMenuItem
ddi.Text = subnode.Attributes("text").Value
ddi.Tag = subnode.InnerText
AddHandler ddi.Click, AddressOf DynamicMenuHandler
tsmi.DropDownItems.Add(ddi)
Next
End If
MenuStrip1.Items.Add(tsmi)
Next
End Sub
A key feature here is that all of the menu items have the same handler for the click event - whether they are top level items or sub-menu items. I called the BuildMenus function from the Form Load event
Here is that handler
Private Sub DynamicMenuHandler(ByVal sender As System.Object, ByVal e As System.EventArgs)
Dim s1 As ToolStripMenuItem = DirectCast(sender, ToolStripMenuItem)
If s1.Tag.ToString.Length > 0 Then
Dim SubType As System.Type = GetType(DynamicMenuSubs)
Dim SubInfo As System.Reflection.MethodInfo = SubType.GetMethod(s1.Tag.ToString())
Dim SubController As New DynamicMenuSubs
SubInfo.Invoke(SubController, Nothing)
End If
End Sub
[EDIT]I've finally re-found the source for the idea of having the functions in a separate controller class. Credit for that idea (on which this solution hinges) is due to
Joris Bijvoets[
^] I can't find his original article but the solution on the link details most of it [/EDIT]