在 VB.NET WinForms 中创建面包屑菜单
提供一个动态菜单,用于钻取数据,或使用新的 Vista 风格的面包屑进行菜单控制。
引言
动态菜单创建并非不寻常。开发人员可以根据用户授权限制菜单选项。他们(我们)也可以在情况需要时添加菜单项,例如表单字段满足特定值。
在 Windows Forms 中,菜单传统上有两种形式:文本和按钮。文本链接是诸如“文件 -> 另存为”之类的项目。按钮就是按钮。
网页可以使用第三种类型的菜单,称为面包屑菜单。这是一种了解您在哪里以及如何到达那里进行导航的好方法。例如:
首页 > 论坛 > .NET > VB.NET > 一般
我最近遇到一个情况,用户希望通过 listviews / datagrids 钻取(数据挖掘)到更深层的内容。他们需要知道自己在哪里 - 就像购物中心里那个说“您在这里”的大地图一样。面包屑!
我知道我的面包屑菜单需要三个关键功能:
- 在每次钻取时添加一个菜单面包屑。
- 让用户能够通过面包屑菜单返回数据。
- 如果用户执行了上述操作,则删除一个菜单选项。
详细说明
面包屑解决方案的第一部分是构建一个用户控件。我会在表单上需要三个这样的控件,因此一个用户控件可以很好地适应 - 好的,而且以后我还可以重用它。
- 构建功能:每次添加菜单项时,都会添加一个符号和菜单项,例如 > Menu1。
LinkLabel
将用于菜单项。 - 删除功能:如果用户点击面包屑链中除最后一个链接之外的任何链接,则应删除所有后续的面包屑。
- 点击功能:当用户点击一个
LinkLabel
时,包含用户控件的表单应接收点击事件并处理正确的面包屑点击。
问题区域
在运行时添加控件很容易。问题是知道在哪里添加控件。为此,用户控件将包含一个私有变量,该变量包含所有控件的当前宽度。使用此方法,每个后续控件都将被添加到正确的位置。
面包屑菜单中的符号 > 将是一个标签。该标签将获得一个标识符,以便于移除。LinkLabel
s 也是如此。每个都将用相同的数字标记 Tag
来标识面包屑集。这对于删除面包屑项很重要。
预编码
创建一个新的 Windows 应用程序项目。添加一个用户控件。将其命名为 ClsBreadCrumb
。将用户控件的大小设置为 480x16。该控件的高度足以容纳一个 LinkLabel
,宽度足以放置在表单上。如果需要,可以在以后在托管表单上调整控件大小。
编码
用户控件
定义私有变量
'used to item group count
Private iItemCount As Integer
'used for proper label placement
Private iIncreasingLength As Integer
构建函数。每次添加新菜单项时都会调用此函数
Public Function AddBreadCrumbLink(ByVal strNewLinkLabel As String)
iItemCount = iItemCount + 1
'add the > symbol
Dim ctrlLK As New Label
ctrlLK.Top = 0
ctrlLK.Left = iIncreasingLength
'create unique name
ctrlLK.Name = "BC" & iItemCount
ctrlLK.Text = ">"
'the tag will be used to identify what
'symbol to delete and what was clicked
ctrlLK.Tag = iItemCount 'strArrayList.Count - 1
'important! autosize the control so everything has a smooth look
ctrlLK.AutoSize = True
'now add the control to your form
Me.Controls.Add(ctrlLK)
'increase the private var so you will know where to
'start your next control
iIncreasingLength = iIncreasingLength + ctrlLK.Width
'add the new linklabel
Dim ctrlLL As New LinkLabel
ctrlLL.Top = 0
ctrlLL.Name = strNewLinkLabel
ctrlLL.Left = iIncreasingLength
ctrlLL.Text = strNewLinkLabel
'the tag will be used to identify what
'linklabel to delete and what was clicked
ctrlLL.Tag = iItemCount
ctrlLL.AutoSize = True
iIncreasingLength = iIncreasingLength + ctrlLL.Width
Me.Controls.Add(ctrlLL)
'add a handler for the linklabel
'same userd for all and we will use the control.tag property
' to see which was clicked
AddHandler ctrlLL.Click, AddressOf myLinkLabel_Click
End Function
Private Sub myLinkLabel_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
'event is raised to the form that holds this control
RaiseEvent ItemClicked(Me, New ItemClickedEventArgs(sender.name))
'we are moving back in the menu so we need to adjust our menu.
RemoveLaterMenuItems(sender.tag)
End Sub
是时候删除那些菜单项了
Private Sub RemoveLaterMenuItems(ByVal strTagIdentifierForMenuDeletion As String)
Dim intValFromMenu As Integer
Dim iMax As Integer
Dim iFor As Integer
Dim iCount As Integer
intValFromMenu = CInt(strTagIdentifierForMenuDeletion)
Do Until ClearMenuItems(intValFromMenu) = True
'each breadcrumb is made up of a label and a linklabel.
'each is tagged with the same number
'each time a set is deleted, we decrease the itemcount by 1
iCount = iCount + 1
If (iCount Mod 2 = 0) Then
iItemCount = iItemCount - 1
End If
Loop
End Sub
Private Function ClearMenuItems(ByVal intValFromMenu As Integer) _
As Boolean
Dim intValFromControl As Integer
ClearMenuItems = False
Dim ThisCtrl As Control
For Each ThisCtrl In Me.Controls
'identify labels and link labels for that
'tag set (1's, 2's, etc.)
intValFromControl = CInt(ThisCtrl.Tag)
If intValFromControl > intValFromMenu Then
iIncreasingLength = iIncreasingLength - ThisCtrl.Width
Me.Controls.Remove(ThisCtrl)
Exit Function
End If
Next
ClearMenuItems = True
End Function
处理引发事件
Public Event ItemClicked(ByVal sender As Object, ByVal e As ItemClickedEventArgs)
Public Class ItemClickedEventArgs
Inherits System.EventArgs
Public ItemText As String
Public Sub New(ByVal Text As String)
Me.ItemText = Text
End Sub
End Class
打开表单并构建项目。在工具栏中,选择“我的用户控件”,然后将控件拖到您的 Form1
表单上。
让我们给用户控件添加一点颜色
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
ClsBreadCrumb1.BackColor = Color.PaleGoldenrod
End Sub
添加一个标记为 cmdAddMenuItem
的 Button
并粘贴以下代码
Private Sub cmdAddMenuItem_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles cmdAddMenuItem.Click
ClsBreadCrumb1.AddBreadCrumbLink("LinkLabel" & icount)
icount = icount + 1
End Sub
icount
计数器仅用于提供不同的菜单项名称。
最后,我们要处理那些点击事件,以便知道用户点击了哪个 LinkLabel
。
Private Sub ClsBreadCrumb1_ItemClicked(ByVal sender As Object, _
ByVal e As clsBreadCrumb.ItemClickedEventArgs) _
Handles ClsBreadCrumb1.ItemClicked
MessageBox.Show(Me, "The item " & e.ItemText & " was clicked.")
End Sub
结论
这是一个非常基础的创建面包屑风格菜单的教程。它可能可以修改为使用 VB 2005 中的控件数组。Microsoft Vista 现在在控制面板等部分使用了面包屑系统,所以我们可能在一年后在应用程序中使用这种风格的菜单。