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:
Private iItemCount As Integer
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
Dim ctrlLK As New Label
ctrlLK.Top = 0
ctrlLK.Left = iIncreasingLength
ctrlLK.Name = "BC" & iItemCount
ctrlLK.Text = ">"
ctrlLK.Tag = iItemCount ctrlLK.AutoSize = True
Me.Controls.Add(ctrlLK)
iIncreasingLength = iIncreasingLength + ctrlLK.Width
Dim ctrlLL As New LinkLabel
ctrlLL.Top = 0
ctrlLL.Name = strNewLinkLabel
ctrlLL.Left = iIncreasingLength
ctrlLL.Text = strNewLinkLabel
ctrlLL.Tag = iItemCount
ctrlLL.AutoSize = True
iIncreasingLength = iIncreasingLength + ctrlLL.Width
Me.Controls.Add(ctrlLL)
AddHandler ctrlLL.Click, AddressOf myLinkLabel_Click
End Function
Private Sub myLinkLabel_Click(ByVal sender As Object, _
ByVal e As System.EventArgs)
RaiseEvent ItemClicked(Me, New ItemClickedEventArgs(sender.name))
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
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
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.