自学Web开发第十六天-基于VB和ASP.NET,深入研究 Menu 控件,从数据库动态加载菜单节点
之前在研究导航的时候粗略研究了一下 Menu 控件,该控件直接绑定 SiteMapDataSource 控件,从 Web.sitemap 加载导航信息。这种方法十分简单,但是不够灵活。所以这里深入研究下从数据库动态加载菜单节点信息。
菜单的结构
整个菜单由一级菜单、二级菜单、三级菜单等各级节点组成。在站点地图中生成的菜单是有个根节点的,而动态添加节点就不需要根节点,直接添加即可。
各级菜单节点均是 MenuItem 对象,只要实例化后,添加到各级菜单上就行。 MenuItem 对象的重要属性如下:
- Enbabled : 启用菜单项
- NavigateUrl :点击菜单项跳转的地址
- Text :菜单项显示的文本
- Value :菜单项的值
- ToolTip : 鼠标放到菜单项上显示的提示
- Selectable :是否可以选择菜单项(即点击菜单项是否跳转页面)
需注意的是,动态添加的菜单项各节点是否显示也收到 Menu 控件的 MaximunDynamicDisplayLevels 属性影响。
一级菜单节点的添加
一级菜单节点直接在控件上添加,创建 MenuItem 对象,然后直接添加到 Menu 对象的 Items 成员里就行。
Dim item As New MenuItem With {
.NavigateUrl = "",
.Value = "001",
.Text = "测试页1",
.ToolTip = "测试1的提示"
.Selectable = False
}
Menu.Items.Add(item)
二级至多级菜单节点的添加
和一级菜单节点的添加不同的是,从二级菜单节点开始,添加 MenuItem 对象要在父节点的 ChildItems 成员里。
Dim item As New MenuItem With {
.NavigateUrl = "",
.Value = "001",
.Text = "测试页1",
.ToolTip = "测试1的提示"
.Selectable = False
}
Menu.Items.Add(item)
Dim child As New MenuItem With {
.Text = "测试子节点1",
.Value = "002",
.Selectable = False
}
item.ChildItems.Add(child)
' 或使用 Menu.Items(0).ChildItems.Add(child) 来添加
使用数据库添加菜单节点
这里假设数据库里获取了一个数据表 table ,表结构为 id / text / parentid(父节点 id) 和其他一些节点项属性信息。当parentid = 0
时,就是一级菜单。
For Each item In menurow '添加一级节点
Dim menuitem As New MenuItem With {
.Text = IIf(IsDBNull(item("text")), "", item("text")), 'iff是三元表达式,判断是否 DBNULL
.Value = IIf(IsDBNull(item("id")), "", item("id")),
.NavigateUrl = IIf(IsDBNull(item("navigateurl")), "", item("navigateurl")),
.ToolTip = IIf(IsDBNull(item("tooltip")), "", item("tooltip")),
.Selectable = IIf(IsDBNull(item("selectable")), "", item("selectable"))
}
menu.Items.Add(menuitem)
Next
For Each i As MenuItem In menu.Items '添加二级节点
Dim rows As DataRow() = table.Select("parentid = " & i.Value)
For Each item In rows
Dim menuitem As New MenuItem With {
.Text = IIf(IsDBNull(item("text")), "", item("text")), 'iff是三元表达式,判断是否 DBNULL
.Value = IIf(IsDBNull(item("id")), "", item("id")),
.NavigateUrl = IIf(IsDBNull(item("navigateurl")), "", item("navigateurl")),
.ToolTip = IIf(IsDBNull(item("tooltip")), "", item("tooltip")),
.Selectable = IIf(IsDBNull(item("selectable")), "", item("selectable"))
}
i.ChildItems.Add(menuitem)
Next
Next
使用递归函数添加全部节点
上面的方法需要一级一级添加节点,不灵活。可以使用递归函数一次性添加全部节点。假设数据表 table 同上。
'使用递归函数添加menu的子节点
Private Sub addMenuNode(menu As Object, table As DataTable)
Dim parentid As Integer '当前节点的id
Dim items As MenuItemCollection '节点的子集
If menu.GetType = GetType(Menu) Then '对参数1进行判断
items = CType(menu, Menu).Items
parentid = 0
ElseIf menu.GetType = GetType(MenuItem) Then
items = CType(menu, MenuItem).ChildItems
parentid = CType(menu, MenuItem).Value
Else
Dim Exception As New ArgumentException("参数menu错误")
Throw Exception
End If
Dim childmenu As DataRow() = table.Select("parentid =" & parentid) '查找子节点的数据
If childmenu.Count = 0 Then Exit Sub '没有子节点
For Each row In childmenu '为本节点添加子节点
Dim menuitem As New MenuItem With {
.Text = IIf(IsDBNull(row("text")), "", row("text")), 'iff是三元表达式,判断是否 DBNULL
.Value = IIf(IsDBNull(row("id")), "", row("id")),
.NavigateUrl = IIf(IsDBNull(row("navigateurl")), "", row("navigateurl")),
.ToolTip = IIf(IsDBNull(row("tooltip")), "", row("tooltip")),
.Selectable = IIf(IsDBNull(row("selectable")), "", row("selectable"))
}
items.Add(menuitem)
Next
For Each child In items '历遍每个子节点
addMenuNode(child, table)
Next
End Sub