詳細(xì)概括VB.NET實現(xiàn)動態(tài)菜單的方法
VB.NET經(jīng)過長時間的發(fā)展,很多用戶都很了解VB.NET實現(xiàn)動態(tài)菜單了,這里我發(fā)表一下個人理解,和大家討論討論。自己寫了一個VB.NET實現(xiàn)動態(tài)菜單的例子,覺得還不錯。例子中用的主要技術(shù)有:
◆菜單樹的操作
◆treeview的操作
◆利用堆棧實現(xiàn)菜單樹與treeview樹成員的對應(yīng)
◆利用委托實現(xiàn)對象與事件的關(guān)聯(lián)
因為我也是初學(xué)者,所以有些詞匯用得可能不恰當(dāng),另外有些理解也可能有偏差。這個例子實現(xiàn)了VB.NET實現(xiàn)動態(tài)菜單,用戶可以在當(dāng)前菜單的任意一個節(jié)點上添加一個子菜單,并為添加的子菜單添加事件。
例子介紹如下:
首先創(chuàng)建一個 VB.NET winform application
在form中添加一個菜單,取名為:MainItem,隨便添加幾個菜單項幾項。
◆添加一個textbox控件, 取名為:txtNewText
◆添加一個listbox控件, 取名為:lstHandlers
◆添加一個TreeView控件,取名為:tvMenu
具體代碼如下(其中有大部分代碼為自動生成):
- Public Class Form1Class Form1
- Inherits System.Windows.Forms.Form
- Windows 窗體設(shè)計器生成的代碼#Region " Windows 窗體設(shè)計器生成的代碼 "
- Public Sub New()Sub New()
- MyBase.New()
- '該調(diào)用是 Windows 窗體設(shè)計器所必需的。
- InitializeComponent()
- '在 InitializeComponent() 調(diào)用之后添加任何初始化
- 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 窗體設(shè)計器所必需的
- Private components As System.ComponentModel.IContainer
- '注意:以下過程是 Windows 窗體設(shè)計器所必需的
- '可以使用 Windows 窗體設(shè)計器修改此過程。
- '不要使用代碼編輯器修改它。
- 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 代表一個樹結(jié)點集合,每一個節(jié)點下的兒子節(jié)點的集合
- '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()'定一個堆棧對象
- '將樹結(jié)點從當(dāng)前節(jié)點一直到根的一條路徑壓入堆棧
- Do Until selectedNode Is Nothing
- indexStack.Push(selectedNode.Index)
- selectedNodeselectedNode = selectedNode.Parent
- Loop
- '再利用菜單與treeview樹一一對應(yīng)的特點.根據(jù)節(jié)點的index,找到對應(yīng)的菜單項.然后沿著路徑找到當(dāng)前的菜單項
- Dim menuItem As MenuItem = MainMenu.MenuItems(indexStack.Pop())
- Do Until indexStack.Count = 0
- menuItemmenuItem = menuItem.MenuItems(indexStack.Pop())
- Loop
- '返回當(dāng)前菜單項
- 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)'將節(jié)點轉(zhuǎn)成菜單項
- 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) '將最新的菜單呈現(xiàn)成樹
- 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)'將菜單樹呈現(xiàn)到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
【編輯推薦】