Create a Breadcrumb Menu in VB.NET WinForms
Provide a dynamic menu for drilling through data, or using the new Vista style of breadcrumbing for menu control.
Introduction
Dynamic menu creation is nothing out of the ordinary. Developers can limit menu options based on user authorization. They (we) can also add menu items if a situation demands it, such as a form field meeting a certain value.
Menus traditionally come in two flavors on Windows Forms: text and buttons. Text links are items such as File->Save As. Buttons are, well, buttons.
Web pages can use a third type of menu known as a breadcrumb menu. It's a great way to see where you are and how you got there. For example:
Home > Forums > .NET > VB.NET > General
I had a recent situation where a user wanted to drill-down (data mine) via listviews / datagrids to deeper content. They needed to know where they were - like the big map at the shopping mall that says "you are here". Breadcrumbs!
I knew that my breadcrumb menu would need three key pieces of functionality:
- Add a menu breadcrumb at each drill down.
- Give user the ability to back up in the data via the breadcrumb menu.
- Remove a menu option if the user did the above.
Details
The first part of the breadcrumb solution was to build a user control. I would need three of these on the form so a user control would fit nicely - OK, and I could reuse it later.
- Build Functionality: Each time a menu item is added, it would add a symbol and the menu item, such as > Menu1. The
LinkLabel
would be used for the menu items. - Remove Functionality: If a user clicks on any link other than the last link in the breadcrumb chain, all the subsequent breadcrumbs should be removed.
- Click Functionality: When the user clicks a
LinkLabel
, the form that holds the user control should receive the click event and process the correct breadcrumb click.
Problem Areas
It's easy to add a control at runtime. The problem is knowing where to add the control. For this reason, the user control will contain a private variable that contains the current width of all controls. Using this method, each subsequent control will be added in the right location.
The symbol > in the breadcrumb menu will be a label. This label will be given an identifier for easy reference for removal. Same goes for the LinkLabel
s. Each will be marked with a Tag
of the same number to identify the breadcrumb set. This is important for removing breadcrumb items.
Pre-coding
Create a new Windows Application project. Add a user control. Name it ClsBreadCrumb
. Size the user control to 480x16. The control will be tall enough to hold a LinkLabel
and wide enough to be placed on a form. The control can be resized on the hosted form at a later time, if necessary.
Coding
User Control
Define the private variables:
'used to item group count
Private iItemCount As Integer
'used for proper label placement
Private iIncreasingLength As Integer
The Build Function. This function will be called each time a new menu item is added:
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
Time to remove those menu items:
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
Dealing with the Raise Events:
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
Open up the form and build the project. In the toolbar, select "My User Controls" and drag the control to your Form1
form.
Let's add a bit of color to the user control:
Private Sub Form1_Load(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles MyBase.Load
ClsBreadCrumb1.BackColor = Color.PaleGoldenrod
End Sub
Add a Button
labeled cmdAddMenuItem
and paste the following code:
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
The icount
counter is only used to provide different menu item names.
Finally, we want to handle those click events so we know what LinkLabel
the user clicked.
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
Conclusion
This is a very basic tutorial on creating a breadcrumb style menu. It could probably be modified for using control arrays in VB 2005. Microsoft Vista now uses the breadcrumb system in the Control Panel section, among others, so we might be using this style of menu in applications a year down the road.