Solved

Making MenuStrip Items visible without using a Loop?

Posted on 2014-02-11
17
1,775 Views
Last Modified: 2014-02-13
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:

   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

Open in new window


Not sure how to make that menu item that is found visible using just the mnu variable (which represents my main menu).
0
Comment
Question by:BlakeMcKenna
  • 9
  • 7
17 Comments
 
LVL 96

Expert Comment

by:Bob Learned
ID: 39853525
Are you using a for loop to create the menu, or are they statically defined in the designer?
0
 
LVL 39

Expert Comment

by:Kyle Abrahams
ID: 39853531
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.

'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

Open in new window

0
 

Author Comment

by:BlakeMcKenna
ID: 39853579
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
0
 

Author Comment

by:BlakeMcKenna
ID: 39853585
LearnedOne,

My menu is statically created in the designer...
0
 

Author Comment

by:BlakeMcKenna
ID: 39853783
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
0
 
LVL 39

Expert Comment

by:Kyle Abrahams
ID: 39853881
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").ToString())
 
     '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
0
 

Author Comment

by:BlakeMcKenna
ID: 39854222
Ok,

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

Open in new window


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.
0
 
LVL 39

Expert Comment

by:Kyle Abrahams
ID: 39854304
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?
0
What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

 

Author Comment

by:BlakeMcKenna
ID: 39854328
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
0
 
LVL 39

Expert Comment

by:Kyle Abrahams
ID: 39854434
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
0
 

Author Comment

by:BlakeMcKenna
ID: 39854566
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".

      mnuItem = mnu.Items(strMenuName)

Open in new window


mnu is the MenuStrip control being passed into the SubRoutine.
0
 

Author Comment

by:BlakeMcKenna
ID: 39854917
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

Open in new window

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.
0
 
LVL 39

Expert Comment

by:Kyle Abrahams
ID: 39856142
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 

Open in new window

0
 

Author Comment

by:BlakeMcKenna
ID: 39856168
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

Open in new window

0
 
LVL 39

Accepted Solution

by:
Kyle Abrahams earned 500 total points
ID: 39856264
doing this by hand.  I've been in the asp.net world for the past few years so a little rusty on windows forms and don't set a project up.  A lot of the code is one for one  which is why I'm able to help out.

I do use references though so I'm not just typing blind:

Has great code in vb.net for iterating through evertything
http://social.msdn.microsoft.com/Forums/windows/en-US/ca49f946-e604-4cf4-9e53-cf171ceca007/enablingdisabling-toolstripmenuitem-objects?forum=winforms

in C# but shows you how to get at the parent/child collection
http://www.codeproject.com/Tips/377155/Iterating-through-menustrip-Items

Showed me that you can make the menu.items collection a toolstripmenuitem collection
http://social.msdn.microsoft.com/Forums/en-US/4de4ddd3-4c09-4e67-b7ba-8b3e892b6565/access-to-toolstripitem-children

I was getting confused between a menuitem, a toolstripitem, a toolstripmenuitem, and a dropdown in the menu.  The following should be a lot closer:

You need a recursive function:
public sub SetVisible(byref item as ToolStripMenuItem, lvlView)
 
               if lvlView = 0
                  item.visible = false
               else 
                  item.visible = true
              end if

                 For Each child As ToolStripMenuItem In item.DropDownItems
                                SetVisible(child, lvlView)
                 Next
end sub


' replace this with what you have
Dim t As ToolStripMenuItem

 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)

                       For Each item As ToolStripItem In mnuItem
                              If item.GetType Is GetType(ToolStripMenuItem) Then
                                  t= item
                                  setVisible(t, lvlView)
                              end if
                       Next

               Next 

Open in new window

0
 

Author Comment

by:BlakeMcKenna
ID: 39856298
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!
0
 
LVL 39

Expert Comment

by:Kyle Abrahams
ID: 39856328
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.
0

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Suggested Solutions

Title # Comments Views Activity
Query datatable in LINQ 6 39
Text in tooltip bound field bridview 3 30
Duplicate a row 2 33
Getfiles in vb.net 28 24
If you're writing a .NET application to connect to an Access .mdb database and use pre-existing queries that require parameters, you've come to the right place! Let's say the pre-existing query(qryCust) in Access takes a Date as a parameter and l…
Since .Net 2.0, Visual Basic has made it easy to create a splash screen and set it via the "Splash Screen" drop down in the Project Properties.  A splash screen set in this manner is automatically created, displayed and closed by the framework itsel…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…
This video gives you a great overview about bandwidth monitoring with SNMP and WMI with our network monitoring solution PRTG Network Monitor (https://www.paessler.com/prtg). If you're looking for how to monitor bandwidth using netflow or packet s…

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now