动态创建MenuStrip - VB.NET
从数据库动态实现MenuStrip,菜单名称和顺序将通过后端控制。
引言
我遇到了一个问题,需要创建一个根据用户权限驱动的应用程序。我想到通过后端实现菜单驱动。所有菜单名称和点击子菜单时要打开的窗体(窗体名)都来自表。为了实现菜单,我使用了 VB.NET 中的 MenuStrip
。
示例代码

Using the Code
它在窗体加载时执行,并填充所有菜单标题。所有数据都来自后端,没有任何硬编码。我附上了两个表 MENUMASTER
和 ACCESS
的结构如下。
下面的代码将有一个变量,例如 iUserAccessMode
,它反过来告诉我们用户访问级别(查看附件的 Excel 表格,并查看 Excel 表格中的 Access 选项卡)。菜单将根据用户访问级别加载。
Private Sub MDIParent1_Load(ByVal sender As Object,
ByVal e As System.EventArgs) Handles Me.Load
'On Error GoTo ErrHandler
'Create a Connection class, that has the full features of working with Backend.
'See article for Connection class : Connection_Class.asp
Dim Conn As New Conn1
Dim mnRd As SqlClient.SqlDataReader
'It helps in populating the MENUs according to user rights. From the Table "Access"
iUserAccessMode = GlobalValues.lblUsrAccess.Text
sQry = ""
sQry = "Select MenuText from MenuMaster Where MainMenuID = 0" & _
" And MenuID in (Select MenuID from Access Where AccessId =
" & CInt(iUserAccessMode) & ")" & _
" And isActive = 1"
mnRd = Conn.ReaderData(sQry)
If mnRd.HasRows Then
mnMenu = New MenuStrip
While mnRd.Read
mnMenu.Items.Add(mnRd(0).ToString, Nothing, New System.EventHandler(
AddressOf MainMenu_OnClick))
Me.Controls.Add(mnMenu)
End While
End If
mnRd.Close()
End Sub
此函数在创建父菜单时创建子菜单。
Private Sub MainMenu_OnClick(ByVal sender As Object, ByVal e As System.EventArgs)
Dim cms As New ContextMenuStrip()
Dim sMenu() As String
Dim Conn As New Conn1
Dim sMenuRD As SqlClient.SqlDataReader
sQry = ""
sQry = "Select MenuID from MenuMaster Where MenuText = '" & sender.ToString & "'"
sMenuRD = Conn.ReaderData(sQry)
Dim parentMenuID As Integer
If sMenuRD.HasRows Then
sMenuRD.Read()
parentMenuID = sMenuRD("MenuID")
End If
sMenuRD.Close()
sQry = ""
sQry = "Select MenuText from MenuMaster Where MainMenuID =
'" & parentMenuID & "'" & _
" And isActive = 1" & _
" And MenuID in (
Select MenuID from Access Where AccessId =
" & CInt(iUserAccessMode) & ")" & _
" Order BY MenuOrder"
sMenuRD = Conn.ReaderData(sQry)
ReDim Preserve sMenu(0)
Dim i As Integer
If sMenuRD.HasRows Then
ReDim Preserve sMenu(0)
i = 0
While sMenuRD.Read()
ReDim Preserve sMenu(i)
sMenu(i) = sMenuRD("MenuText")
i = i + 1
End While
End If
sMenuRD.Close()
For Each sMn As String In sMenu
cms.Items.Add(sMn, Nothing,
New System.EventHandler(AddressOf SelectedChildMenu_OnClick))
Next
Dim tsi As ToolStripMenuItem = CType(sender, ToolStripMenuItem)
tsi.DropDown = cms
End Sub
此函数在每个菜单项的点击事件中执行,要打开的窗体(FormName
)也在事件执行时从后端表 "MENUMASTER
" 中获取。
Private Sub SelectedChildMenu_OnClick(ByVal sender As Object,
ByVal e As System.EventArgs)
Dim Conn As New Conn1
Dim sMenuRD As SqlClient.SqlDataReader
Dim frmName As String = ""
Dim frm As New Form
sQry = ""
sQry = "Select FormName from MenuMaster Where MenuText = '" &
sender.ToString & "'"
sMenuRD = Conn.ReaderData(sQry)
If sMenuRD.HasRows Then
sMenuRD.Read()
frmName = sMenuRD(0).ToString
DynamicallyLoadedObject(frmName).Show(Me)
Else
MsgBox("Under Construction", MsgBoxStyle.Exclamation, "Technical Error")
End If
sMenuRD.Close()
End Sub
关注点
我遇到了将从 SQL 获取的 string
类型的窗体名转换为 FORM
对象的问题。此函数有助于将从 SQL 返回的 string
对象 formName
转换为 Form
类型的对象。
Private Function DynamicallyLoadedObject(ByVal objectName As String,
Optional ByVal args() As Object = Nothing) As Form
Dim returnObj As Object = Nothing
Dim Type As Type = Assembly.GetExecutingAssembly().GetType(
"[YOUR PROJECT NAME]." & objectName)
If Type IsNot Nothing Then
returnObj = Activator.CreateInstance(Type, args)
End If
Return returnObj
End Function
历史
- 2007 年 6 月 17 日:初始发布