65.9K
CodeProject 正在变化。 阅读更多。
Home

在 VB.NET WinForms 中创建面包屑菜单

starIconstarIconstarIconemptyStarIconemptyStarIcon

3.00/5 (3投票s)

2007年2月21日

CPOL

3分钟阅读

viewsIcon

69840

downloadIcon

961

提供一个动态菜单,用于钻取数据,或使用新的 Vista 风格的面包屑进行菜单控制。

Screenshot - breadcrumb.gif

引言

动态菜单创建并非不寻常。开发人员可以根据用户授权限制菜单选项。他们(我们)也可以在情况需要时添加菜单项,例如表单字段满足特定值。

在 Windows Forms 中,菜单传统上有两种形式:文本和按钮。文本链接是诸如“文件 -> 另存为”之类的项目。按钮就是按钮。

网页可以使用第三种类型的菜单,称为面包屑菜单。这是一种了解您在哪里以及如何到达那里进行导航的好方法。例如:

首页 > 论坛 > .NET > VB.NET > 一般

我最近遇到一个情况,用户希望通过 listviews / datagrids 钻取(数据挖掘)到更深层的内容。他们需要知道自己在哪里 - 就像购物中心里那个说“您在这里”的大地图一样。面包屑!

我知道我的面包屑菜单需要三个关键功能

  1. 在每次钻取时添加一个菜单面包屑。
  2. 让用户能够通过面包屑菜单返回数据。
  3. 如果用户执行了上述操作,则删除一个菜单选项。

详细说明

面包屑解决方案的第一部分是构建一个用户控件。我会在表单上需要三个这样的控件,因此一个用户控件可以很好地适应 - 好的,而且以后我还可以重用它。

  • 构建功能:每次添加菜单项时,都会添加一个符号和菜单项,例如 > Menu1。LinkLabel 将用于菜单项。
  • 删除功能:如果用户点击面包屑链中除最后一个链接之外的任何链接,则应删除所有后续的面包屑。
  • 点击功能:当用户点击一个 LinkLabel 时,包含用户控件的表单应接收点击事件并处理正确的面包屑点击。

问题区域

在运行时添加控件很容易。问题是知道在哪里添加控件。为此,用户控件将包含一个私有变量,该变量包含所有控件的当前宽度。使用此方法,每个后续控件都将被添加到正确的位置。

面包屑菜单中的符号 > 将是一个标签。该标签将获得一个标识符,以便于移除。LinkLabels 也是如此。每个都将用相同的数字标记 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

添加一个标记为 cmdAddMenuItemButton 并粘贴以下代码

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 现在在控制面板等部分使用了面包屑系统,所以我们可能在一年后在应用程序中使用这种风格的菜单。

© . All rights reserved.