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
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