VB.NET经过长时间的发展,很多用户都很了解VB.NET实现动态菜单了,这里我发表一下个人理解,和大家讨论讨论。自己写了一个VB.NET实现动态菜单的例子,觉得还不错。例子中用的主要技术有:
◆菜单树的操作
◆treeview的操作
◆利用堆栈实现菜单树与treeview树成员的对应
◆利用委托实现对象与事件的关联
因为我也是初学者,所以有些词汇用得可能不恰当,另外有些理解也可能有偏差。这个例子实现了VB.NET实现动态菜单,用户可以在当前菜单的任意一个节点上添加一个子菜单,并为添加的子菜单添加事件。
例子介绍如下:
首先创建一个 VB.NET winform application
在form中添加一个菜单,取名为:MainItem,随便添加几个菜单项几项。
◆添加一个textbox控件, 取名为:txtNewText
◆添加一个listbox控件, 取名为:lstHandlers
◆添加一个TreeView控件,取名为:tvMenu
具体代码如下(其中有大部分代码为自动生成):
- Public Class Form1Class Form1
- Inherits System.Windows.Forms.Form
- Windows 窗体设计器生成的代码#Region " Windows 窗体设计器生成的代码 "
- Public Sub New()Sub New()
- MyBase.New()
- '该调用是 Windows 窗体设计器所必需的。
- InitializeComponent()
- '在 InitializeComponent() 调用之后添加任何初始化
- End Sub
- '窗体重写处置以清理组件列表。
- Protected Overloads Overrides Sub Dispose()Sub Dispose(ByVal disposing As Boolean)
- If disposing Then
- If Not (components Is Nothing) Then
- components.Dispose()
- End If
- End If
- MyBase.Dispose(disposing)
- End Sub
- 'Windows 窗体设计器所必需的
- Private components As System.ComponentModel.IContainer
- '注意:以下过程是 Windows 窗体设计器所必需的
- '可以使用 Windows 窗体设计器修改此过程。
- '不要使用代码编辑器修改它。
- Friend WithEvents MainMenu As System.Windows.Forms.MainMenu
- Friend WithEvents MenuItem1 As System.Windows.Forms.MenuItem
- Friend WithEvents MenuItem2 As System.Windows.Forms.MenuItem
- Friend WithEvents MenuItem3 As System.Windows.Forms.MenuItem
- Friend WithEvents lstHandlers As System.Windows.Forms.ListBox
- Friend WithEvents Label3 As System.Windows.Forms.Label
- Friend WithEvents tvMenu As System.Windows.Forms.TreeView
- Friend WithEvents Label2 As System.Windows.Forms.Label
- Friend WithEvents Label1 As System.Windows.Forms.Label
- Friend WithEvents txtNewText As System.Windows.Forms.TextBox
- Friend WithEvents btnAddItem As System.Windows.Forms.Button
- <System.Diagnostics.DebuggerStepThrough()>
Private Sub InitializeComponent()Sub InitializeComponent()- Me.components = New System.ComponentModel.Container
- Me.MainMenu = New System.Windows.Forms.MainMenu(Me.components)
- Me.MenuItem1 = New System.Windows.Forms.MenuItem
- Me.MenuItem2 = New System.Windows.Forms.MenuItem
- Me.MenuItem3 = New System.Windows.Forms.MenuItem
- Me.lstHandlers = New System.Windows.Forms.ListBox
- Me.Label3 = New System.Windows.Forms.Label
- Me.tvMenu = New System.Windows.Forms.TreeView
- Me.Label2 = New System.Windows.Forms.Label
- Me.Label1 = New System.Windows.Forms.Label
- Me.txtNewText = New System.Windows.Forms.TextBox
- Me.btnAddItem = New System.Windows.Forms.Button
- Me.SuspendLayout()
- '
- 'MainMenu
- '
- Me.MainMenu.MenuItems.AddRange
(New System.Windows.Forms.MenuItem() {Me.MenuItem1, Me.MenuItem2, Me.MenuItem3})- '
- 'MenuItem1
- '
- Me.MenuItem1.Index = 0
- Me.MenuItem1.Text = "菜单1"
- '
- 'MenuItem2
- '
- Me.MenuItem2.Index = 1
- Me.MenuItem2.Text = "菜单2"
- '
- 'MenuItem3
- '
- Me.MenuItem3.Index = 2
- Me.MenuItem3.Text = "菜单3"
- '
- 'lstHandlers
- '
- Me.lstHandlers.ItemHeight = 12
- Me.lstHandlers.Location = New System.Drawing.Point(88, 64)
- Me.lstHandlers.Name = "lstHandlers"
- Me.lstHandlers.Size = New System.Drawing.Size(136, 112)
- Me.lstHandlers.TabIndex = 13
- '
- 'Label3
- '
- Me.Label3.Location = New System.Drawing.Point(56, 64)
- Me.Label3.Name = "Label3"
- Me.Label3.Size = New System.Drawing.Size(32, 16)
- Me.Label3.TabIndex = 12
- Me.Label3.Text = "事件"
- '
- 'tvMenu
- '
- Me.tvMenu.Location = New System.Drawing.Point(280, 24)
- Me.tvMenu.Name = "tvMenu"
- Me.tvMenu.Size = New System.Drawing.Size(152, 152)
- Me.tvMenu.TabIndex = 11
- '
- 'Label2
- '
- Me.Label2.Location = New System.Drawing.Point(232, 32)
- Me.Label2.Name = "Label2"
- Me.Label2.Size = New System.Drawing.Size(48, 16)
- Me.Label2.TabIndex = 10
- Me.Label2.Text = "添加到"
- '
- 'Label1
- '
- Me.Label1.Location = New System.Drawing.Point(8, 32)
- Me.Label1.Name = "Label1"
- Me.Label1.Size = New System.Drawing.Size(80, 16)
- Me.Label1.TabIndex = 9
- Me.Label1.Text = "新菜单项文字"
- '
- 'txtNewText
- '
- Me.txtNewText.Location = New System.Drawing.Point(88, 24)
- Me.txtNewText.Name = "txtNewText"
- Me.txtNewText.Size = New System.Drawing.Size(136, 21)
- Me.txtNewText.TabIndex = 8
- '
- 'btnAddItem
- '
- Me.btnAddItem.Location = New System.Drawing.Point(168, 192)
- Me.btnAddItem.Name = "btnAddItem"
- Me.btnAddItem.Size = New System.Drawing.Size(80, 24)
- Me.btnAddItem.TabIndex = 7
- Me.btnAddItem.Text = "添加菜单项"
- '
- 'Form1
- '
- Me.AutoScaleBaseSize = New System.Drawing.Size(6, 14)
- Me.ClientSize = New System.Drawing.Size(448, 225)
- Me.Controls.Add(Me.lstHandlers)
- Me.Controls.Add(Me.Label3)
- Me.Controls.Add(Me.tvMenu)
- Me.Controls.Add(Me.Label2)
- Me.Controls.Add(Me.Label1)
- Me.Controls.Add(Me.txtNewText)
- Me.Controls.Add(Me.btnAddItem)
- MeMe.Menu = Me.MainMenu
- Me.Name = "Form1"
- Me.Text = "Form1"
- Me.ResumeLayout(False)
- Me.PerformLayout()
- End Sub
- #End Region
- Private eHandlers(3) As EventHandler '定义事件方法集合
- Private Sub ShowHelloWorld()Sub ShowHelloWorld(ByVal sender As System.Object,
ByVal e As System.EventArgs)- MessageBox.Show("Hello World!")
- End Sub
- Private Sub ShowMenuItemText()Sub ShowMenuItemText(ByVal sender As System.Object,
ByVal e As System.EventArgs)- Dim mItem As MenuItem
- mItem = CType(sender, MenuItem)
- MessageBox.Show(mItem.Text)
- End Sub
- Private Sub ShowMenuItemIndex()Sub ShowMenuItemIndex(ByVal sender As System.Object,
ByVal e As System.EventArgs)- Dim mItem As MenuItem
- mItem = CType(sender, MenuItem)
- MessageBox.Show(mItem.Index)
- End Sub
- Private Sub ShowCurDateTime()Sub ShowCurDateTime(ByVal sender As System.Object,
ByVal e As System.EventArgs)- Dim strDate As String = DateTime.Now.ToString()
- MessageBox.Show(strDate)
- End Sub
- Private Sub MenuItemToNode()Sub MenuItemToNode(ByVal menuItems As Menu.MenuItemCollection,
ByVal targetNodes As TreeNodeCollection)- 'TreeNodeCollection 代表一个树结点集合,每一个节点下的儿子节点的集合
- 'MenuItemCollection 代表一个菜单项的集合,也是菜单树中某一菜单下的一级子菜单的菜单项的集合
- Dim subItem As MenuItem
- For Each subItem In menuItems
- Dim subNode As New TreeNode(subItem.Text)
- If subItem.MenuItems.Count > 0 Then
- MenuItemToNode(subItem.MenuItems, subNode.Nodes)'递归处理
- End If
- targetNodes.Add(subNode)
- Next
- End Sub
- Private Function FindMenuItem()Function FindMenuItem(ByVal selectedNode As TreeNode) As MenuItem
- Dim indexStack As New Collections.Stack()'定一个堆栈对象
- '将树结点从当前节点一直到根的一条路径压入堆栈
- Do Until selectedNode Is Nothing
- indexStack.Push(selectedNode.Index)
- selectedNodeselectedNode = selectedNode.Parent
- Loop
- '再利用菜单与treeview树一一对应的特点.根据节点的index,找到对应的菜单项.然后沿着路径找到当前的菜单项
- Dim menuItem As MenuItem = MainMenu.MenuItems(indexStack.Pop())
- Do Until indexStack.Count = 0
- menuItemmenuItem = menuItem.MenuItems(indexStack.Pop())
- Loop
- '返回当前菜单项
- Return menuItem
- End Function
- Private Sub btnAddItem_Click()Sub btnAddItem_Click(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles btnAddItem.Click- If txtNewText.Text = "" Then Exit Sub
- If tvMenu.SelectedNode Is Nothing Then Exit Sub
- Dim correspondingMenuItem As MenuItem
- Dim newMenuItem As MenuItem
- correspondingMenuItem = FindMenuItem(tvMenu.SelectedNode)'将节点转成菜单项
- newMenuItem = New MenuItem(txtNewText.Text) '生成新加的菜单项
- If lstHandlers.SelectedIndex >= 0 Then
- AddHandler newMenuItem.Click, eHandlers(lstHandlers.SelectedIndex) '建立事件的委托
- End If
- correspondingMenuItem.MenuItems.Add(newMenuItem)'将新菜单加到菜单树中
- tvMenu.Nodes.Clear() '清空treeview树
- MenuItemToNode(MainMenu.MenuItems, tvMenu.Nodes) '将最新的菜单呈现成树
- tvMenu.ExpandAll() '展开树
- End Sub
- Private Sub Form1_Load()Sub Form1_Load(ByVal sender As System.Object,
ByVal e As System.EventArgs) Handles MyBase.Load- MenuItemToNode(MainMenu.MenuItems, tvMenu.Nodes)'将菜单树呈现到treeview中
- tvMenu.ExpandAll() '展开他
- '将三个事件方法放入集合
- eHandlers(0) = AddressOf ShowHelloWorld
- eHandlers(1) = AddressOf ShowMenuItemText
- eHandlers(2) = AddressOf ShowMenuItemIndex
- eHandlers(3) = AddressOf ShowCurDateTime
- '将事件方法名字写入列表
- Dim i As Integer
- For i = 0 To eHandlers.Length - 1
- lstHandlers.Items.Add(eHandlers(i).Method.Name)
- Next
- End Sub
- End Class
【编辑推荐】