BlakeMcKenna
asked on
Making MenuStrip Items visible without using a Loop?
I think I found a way to control the menu options visibility in my MDI Form menu but not quite sure how to implement it.
I'm basically storing a key value in the database for each menu item. I use one loop in which to retrieve these values and then do something like this:
Not sure how to make that menu item that is found visible using just the mnu variable (which represents my main menu).
I'm basically storing a key value in the database for each menu item. I use one loop in which to retrieve these values and then do something like this:
Dim blnFound As Boolean = False
blnFound = mnu.Items.ContainsKey(mnu_Key)
If blnFound Then
Not sure how to take this menu item and make it visible
End If
Not sure how to make that menu item that is found visible using just the mnu variable (which represents my main menu).
Are you using a for loop to create the menu, or are they statically defined in the designer?
From:
http://msdn.microsoft.com/en-us/library/system.windows.forms.toolstripitemcollection(v=vs.110).aspx
Note that my VB is a little off . . . it's been forever so it may have syntax errors. Essentially you want to get the array of items and loop over the array turning each item visible to false.
http://msdn.microsoft.com/en-us/library/system.windows.forms.toolstripitemcollection(v=vs.110).aspx
Note that my VB is a little off . . . it's been forever so it may have syntax errors. Essentially you want to get the array of items and loop over the array turning each item visible to false.
'get the array of items that have the key. It's possible to have the same key for multiple items.
Dim mnuItems as ToolStripItemCollection() = mnu.Items.Find(mnu_Key)
'if there are no items this lopp is skipped.
For Each item as ToolStripItem in mnuItems
item.Visible = false
next
ASKER
Kyle,
Your VB is a little off but that's ok. I've never used a ToolStripItemCollection before. I got the following error in the declaration (see screenshot).
Thanks!
Screenshot.jpg
Your VB is a little off but that's ok. I've never used a ToolStripItemCollection before. I got the following error in the declaration (see screenshot).
Thanks!
Screenshot.jpg
ASKER
LearnedOne,
My menu is statically created in the designer...
My menu is statically created in the designer...
ASKER
Perhaps I should explain the whole concept of what I'm trying to do.
My menu structure for my application is already defined within the Designer. The visible property is set to False for each menu item, including the 1st level items.
Each user has their own set of permissions which are defined in a SQL Server DB. I have attached an image of the recordset for a specific user. The definitions of the columns are as follows:
menuName - contains the value of the "Name" property of the menu item
functionality - contains the menu item literal value
lvlUpdate - a boolean flag indicating whether the user has update privileges for that
menu item functionality
lvlView - a boolean flag indicating whether the user has viewing privileges for that
menu item functionality
userID - the ID of the User that is logged into the application
functionKey - a literal value that is added to the StatusStrip
hasBar - a boolean value indicating if a ToolStripSeparatorBar should be shown after
the previous menu item.
I basically read the DB Table and based on whatever records are in the dataset, I need to set the "Visible" property for that specific menu item to true. I'm just not sure of the best way to do this. I know there are several different "ToolStrip*" objects to use.
I hope I've explained this properly. If anything is unclear, please let me know.
Thanks!
Screenshot.jpg
My menu structure for my application is already defined within the Designer. The visible property is set to False for each menu item, including the 1st level items.
Each user has their own set of permissions which are defined in a SQL Server DB. I have attached an image of the recordset for a specific user. The definitions of the columns are as follows:
menuName - contains the value of the "Name" property of the menu item
functionality - contains the menu item literal value
lvlUpdate - a boolean flag indicating whether the user has update privileges for that
menu item functionality
lvlView - a boolean flag indicating whether the user has viewing privileges for that
menu item functionality
userID - the ID of the User that is logged into the application
functionKey - a literal value that is added to the StatusStrip
hasBar - a boolean value indicating if a ToolStripSeparatorBar should be shown after
the previous menu item.
I basically read the DB Table and based on whatever records are in the dataset, I need to set the "Visible" property for that specific menu item to true. I'm just not sure of the best way to do this. I know there are several different "ToolStrip*" objects to use.
I hope I've explained this properly. If anything is unclear, please let me know.
Thanks!
Screenshot.jpg
in this case you would loop over the record set:
'assuming you know how to setup the cmd, connection params.
Dim dr as SqlDataReader = cmd.ExecuteReader()
Dim item as ToolStripItem
While (dr.Read())
'you can access the item by name
item = mnu.Items(dr("menuName").T oString())
'check for existance
if item is not nothing then
'true? -> set visible
item.visible = true
else
'doesn't exist, show error.
MsgBox ("Could not find menu item: " + dr("menuName").ToString()
end if
wend
'assuming you know how to setup the cmd, connection params.
Dim dr as SqlDataReader = cmd.ExecuteReader()
Dim item as ToolStripItem
While (dr.Read())
'you can access the item by name
item = mnu.Items(dr("menuName").T
'check for existance
if item is not nothing then
'true? -> set visible
item.visible = true
else
'doesn't exist, show error.
MsgBox ("Could not find menu item: " + dr("menuName").ToString()
end if
wend
ASKER
Ok,
Here is what I have so far and it works up to a point.
This logic works up until the menu item is a DropDownItem. When the mnuItem is a DropDownItem, I get that "Object reference not set to an instance of an object" error.
Here is what I have so far and it works up to a point.
Dim mnuItem As ToolStripItem
For Each row As DataRow In EH.DataTable.Rows
strMenuName = "" & row(0)
lvlView = "" & CInt(row(3))
strFKey = "" & row(5)
If strFKey.Length > 0 Then
gFKeys &= strFKey & " ¦ "
End If
mnuItem = mnu.Items(strMenuName)
If lvlView <> 0 Then
mnuItem.Visible = True 'Receive Error Here
End If
Next
This logic works up until the menu item is a DropDownItem. When the mnuItem is a DropDownItem, I get that "Object reference not set to an instance of an object" error.
Just a note, NEVER use row(<int>). Always call the column by name. As soon as someone changes the query, (eg: says I want this primary key field up front or something) it'll break the code. Referencing it by name almost guarantees it will never break. (I say almost cause someone can change the column name, but then that's on them).
Can you post your menu design?
Can you post your menu design?
ASKER
That makes sense...thanks for the tip! I have attached several screenshots of the menu structure. BTW, is there a way to expand the entire menu structure so a snapshot can be taken?
screen-File-SubMenu.jpg
screen-Calibration-SubMenu.jpg
screen-Setups-SubMenu.jpg
screen-Help-SubMenu.jpg
screen-File-SubMenu.jpg
screen-Calibration-SubMenu.jpg
screen-Setups-SubMenu.jpg
screen-Help-SubMenu.jpg
Unfortunately not. Just noticed you're checking on the view permission, not on the menu item itself:
If lvlView <> 0 AndAlso mnuItem is Not Nothing Then
mnuItem.Visible = True 'Receive Error Here
End If
If lvlView <> 0 AndAlso mnuItem is Not Nothing Then
mnuItem.Visible = True 'Receive Error Here
End If
ASKER
It's still not working. What I discovered is that if the database menu item is a DropDownItem rather than a Menu Item, it won't load the menu item name into the mnuItem variable consequently making it equal to "nothing".
mnu is the MenuStrip control being passed into the SubRoutine.
mnuItem = mnu.Items(strMenuName)
mnu is the MenuStrip control being passed into the SubRoutine.
ASKER
This is what I have so far. I'm trying different things but to no avail.
For Each row As DataRow In EH.DataTable.Rows
Dim mnuItem(0) As ToolStripItem
strMenuName = "" & row("menuName")
lvlView = "" & CInt(row("lvlView"))
strFKey = "" & row("functionKey")
hasBar = "" & row("hasBar")
If strFKey.Length > 0 Then
gFKeys &= strFKey & " ¦ "
End If
mnuItem = mnu.Items.Find(strMenuName, True)
If lvlView <> 0 AndAlso Not mnuItem Is Nothing Then
If mnuItem(0).Visible = True Then 'INDEX OUT OF BOUNDS ERROR
mnuItem(0).Visible = False
Else
mnuItem(0).Visible = True
End If
End If
Next
Using the above code, I keep getting an "Index was outside the bounds of the array" error on the indicated line. It happens on the 2nd iteration of the For Loop.
For Each row As DataRow In EH.DataTable.Rows
Dim mnuItems As ToolStripItem()
strMenuName = "" & row("menuName")
lvlView = "" & CInt(row("lvlView"))
strFKey = "" & row("functionKey")
hasBar = "" & row("hasBar")
If strFKey.Length > 0 Then
gFKeys &= strFKey & " ¦ "
End If
mnuItems = mnu.Items.Find(strMenuName, True)
'if you have permissions
If lvlView <> 0 Then
'loop through each menu item and set it to true. No need to check
for each item as ToolStripItem in mnuItems
item.Visible = True
next
Else
'otherwise, loop through each item with the key and set it to false.
for each item as ToolStripItem in mnuItems
item.Visible = False
next
End If
Next
ASKER
Kyle have you tested this? I only ask because it still only shows the 1st level of menu items and not the 2nd level. Here is what I have!
For Each row As DataRow In EH.DataTable.Rows
Dim mnuItem As ToolStripItem()
strMenuName = "" & row("menuName")
lvlView = "" & CInt(row("lvlView"))
strFKey = "" & row("functionKey")
hasBar = "" & row("hasBar")
If strFKey.Length > 0 Then
gFKeys &= strFKey & " ¦ "
End If
mnuItem = mnu.Items.Find(strMenuName, True)
If lvlView <> 0 Then
For Each item As ToolStripItem In mnuItem
item.Visible = True
Next
Else
For Each item As ToolStripItem In mnuItem
item.Visible = False
Next
End If
Next
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Kyle,
Your code works but it goes back to what I had successfully used before and that was using several For Loops. I'll just have to trade a little performance for functionality.
Your code does actually eliminate 1 For Loop so it's an improvement over my code.
Thanks for your help!
Your code works but it goes back to what I had successfully used before and that was using several For Loops. I'll just have to trade a little performance for functionality.
Your code does actually eliminate 1 For Loop so it's an improvement over my code.
Thanks for your help!
It looks like a necessary evil in this case.
If you're not controlling sub items, you could get away with leaving them visible and only turning on the parent. (The theory being if the parent is hidden the children should be as well).
If you are hiding sub elements then you need:
- A for to process your database
- A for loop for every item (and subitems of items recursively)
Right now you only have 2 levels but you can have more than that. This code should handle N levels.
Best of luck, glad we got it working.
If you're not controlling sub items, you could get away with leaving them visible and only turning on the parent. (The theory being if the parent is hidden the children should be as well).
If you are hiding sub elements then you need:
- A for to process your database
- A for loop for every item (and subitems of items recursively)
Right now you only have 2 levels but you can have more than that. This code should handle N levels.
Best of luck, glad we got it working.