EXAMPLE: fill menu from path

P

Patrick F

I am working on a database viewer app that allows the user to input
rowfilters. I wanted the ability to store any given filter to a user file,
and be able to display it in a user organized menu system. I had a VB6 app
that stored displayed items like this with a treeview display, but I wanted
to display the stored values in a menu system. I found no examples of this
on the net, plenty to display in treeviews, but nothing for a menu system,
so I am sharing my solution for 2 reasons:

1. maybe it's not so bad and could help someone out who wants to do
something similar
2. maybe it's not so great and someone could guide me to a cleaner/more
efficient solution

I store the queries/filters in the format of: path\name , as you can see in
the form load. So the trick was turning that into a structured menu leading
to each filter item, certainly not so difficult for some of you, but I was
quite pleased to get it working so well


Code is ready to paste, no form setup needed, it's all done in code.
--------------------------------------------------------------------

Public Class Form1
Dim testPaths(3) As String
Dim ts1 As New System.Windows.Forms.ToolStrip
Dim btn1 As New System.Windows.Forms.ToolStripButton
Dim ddbtnTest As New ToolStripDropDownButton
Dim txt1 As New TextBox
Dim mRoot As New ToolStripMenuItem
Dim m As ToolStripMenuItem

Sub initForm()
Me.MinimumSize = New System.Drawing.Size(300, 300)
Me.MaximumSize = New System.Drawing.Size(500, 500)
Me.Controls.AddRange(New Control() {ts1, txt1})
'ts1
ts1.Items.AddRange(New System.Windows.Forms.ToolStripItem() {btn1})
ts1.Dock = DockStyle.Top
ts1.Name = "ts1"
'btn1
btn1.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text
btn1.Name = "btn1"
btn1.Text = "Load Menu"
AddHandler btn1.Click, AddressOf btn1_Click1
'tx1
txt1.Location = New System.Drawing.Point(0, ts1.Height)
txt1.Multiline = True
txt1.Name = "txt1"
txt1.Size = New System.Drawing.Size(Width - 10, Height - ts1.Height - 40)
txt1.ScrollBars = ScrollBars.Both
txt1.Anchor = AnchorStyles.Left + AnchorStyles.Right + AnchorStyles.Bottom +
AnchorStyles.Top
'ddbtnTest
ts1.Items.Add(ddbtnTest)
ddbtnTest.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text
ddbtnTest.Name = "ddbtnField"
ddbtnTest.Text = "FilterField:"
ddbtnTest.ToolTipText = "FilterField: Field to filter by when typing in
FilterBox"
End Sub

Sub buildMainMenu()
ddbtnTest.DropDownItems.Clear()
For x As Integer = 1 To 3
ddbtnTest.DropDownItems.Add("item " & x.ToString)
Next
'initial menu
Dim mnuFixed As New ToolStripMenuItem 'this item always displayed in menu
ddbtnTest.DropDownItems.AddRange _
(New ToolStripItem() {New ToolStripSeparator, mRoot})
mRoot.DropDownItems.AddRange _
(New ToolStripItem() {mnuFixed, New ToolStripSeparator})
mRoot.Text = "RowFilters"
mnuFixed.Name = "ManageRowFilters"
mnuFixed.Text = "Manage RowFilters"
AddHandler mRoot.DropDownItemClicked, AddressOf RowFilters_click
End Sub

Sub buildFilterMenu()
For Each path As String In testPaths
If path <> "" Then parsePath(path)
Next
End Sub

Sub parsePath(ByVal path As String)
m = mRoot 'set our temp menu item to root
'fill array with each item in path string
Dim paths() As String = Split(path, "\")
Dim count As Integer = 0
Dim typ As String
For Each name As String In paths
If name <> "" Then
'check to see if this is the last (or only) item in the path, if so, it's
our filter item
If count >= paths.Length - 2 Then 'for some reason array.length returns an
extra, so subtract 2
typ = ":FILTER:"
Else
typ = ":FOLDER:"
End If
'count will give us the level in the path: level:0\level:2\etc.
Dim key As String = count & typ & name
addFilter(name, typ, key, count)
count += 1
End If
Next
End Sub

Sub addFilter(ByVal name As String, ByVal typ As String, ByVal key As
String, ByVal level As Integer)
' test if this item has already been added at this level
' - key string filters for level
For Each itm As ToolStripItem In m.DropDownItems
If itm.Name = key Then 'this item alread at this level
' set out temp menu to this level so we are ready to add items at next level
m = itm
Exit Sub
End If
Next
' must be a new item. in actual project it will be .Add(name)
' but this way gives a good visual of the items going in the correct
location
Dim newItm As ToolStripMenuItem = m.DropDownItems.Add(key)
newItm.Name = key
newItm.Tag = "filter value for " & name
newItm.ToolTipText = newItm.Tag
' set out temp menu to this level so we are ready to add items at next level
m = newItm
'add handler so you can process menu item clicks
If typ = ":FOLDER:" Then _
AddHandler m.DropDownItemClicked, AddressOf RowFilters_click
End Sub

Sub clearFilterMenu()
Dim i As Integer = 2 'index of first filter folder/item if there is one
Do While mRoot.DropDownItems.Count > i
mRoot.DropDownItems.Remove(mRoot.DropDownItems.Item(i))
Loop
End Sub

Sub RowFilters_click(ByVal sender As Object, ByVal e As
System.Windows.Forms.ToolStripItemClickedEventArgs)
If e.ClickedItem.Name.Contains(":FILTER:") Then
txt1.Text += e.ClickedItem.Tag & vbNewLine
ElseIf e.ClickedItem.Name.Contains("ManageRowFilters") Then
txt1.Text += e.ClickedItem.Name & vbNewLine
End If
End Sub

Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs)
Handles Me.Load
' this is the format my filter items are stored in
testPaths(0) = "\videos\tv shows\lost"
testPaths(1) = "\videos\tv shows\the office"
testPaths(2) = "\data\date filter"
testPaths(3) = "main filter"
initForm()
buildMainMenu()
End Sub

Private Sub btn1_Click1()
btn1.Checked = Not btn1.Checked
If btn1.Checked Then
buildFilterMenu()
btn1.Text = "Clear Menu"
Else
clearFilterMenu()
btn1.Text = "Load Menu"
End If
End Sub

End Class
 
A

Armin Zingler

Patrick F said:
I am working on a database viewer app that allows the user to input
rowfilters. I wanted the ability to store any given filter to a user
file, and be able to display it in a user organized menu system. I
had a VB6 app that stored displayed items like this with a treeview
display, but I wanted to display the stored values in a menu system.
I found no examples of this on the net, plenty to display in
treeviews, but nothing for a menu system, so I am sharing my
solution for 2 reasons:

1. maybe it's not so bad and could help someone out who wants to do
something similar
2. maybe it's not so great and someone could guide me to a
cleaner/more efficient solution

I store the queries/filters in the format of: path\name , as you can
see in the form load. So the trick was turning that into a
structured menu leading to each filter item, certainly not so
difficult for some of you, but I was quite pleased to get it working
so well

At least you should enable Option Strict in order to be notified of
possible erros ASAP (at compile time). One error is in the line
"AddHandler btn1.Click, AddressOf btn1_Click1". The signature does not
match and will lead to an Exception.


Armin
 
P

Patrick F

I appreciate the feedback Armin. I enabled the "Option Strict" but the
handler works fine on my system.
 
A

Armin Zingler

Patrick F said:
I appreciate the feedback Armin. I enabled the "Option Strict" but
the handler works fine on my system.

The signature of the ToolStripItem's click event is:

Public Event Click(ByVal sender As Object, _
ByVal e As System.EventArgs)

While your code is:

AddHandler btn1.Click, AddressOf btn1_Click1
and
Private Sub btn1_Click1()
End Sub


Obviously the signatures don't match. The handler needs two args.
Therefore it is hard to believe that it can be compiled. I can't,
neither in VB 2008 nor 2005. This is the error message I get:

"Method 'Private Sub btn1_Click1()' does not have a signature compatible
with delegate 'Delegate Sub EventHandler(sender As Object, e As
System.EventArgs)'"



Armin
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top