Click here to Skip to main content
Click here to Skip to main content

Dynamic Menu Based on Database

By , 10 Nov 2005
 
Prize winner in Competition "VB.NET Sep 2005"

Introduction

I searched around for a menu based on a database, where each user in the database would "see" a different menu in the application depending on his permissions and privileges. Since I couldn't find one, I came up with a simple idea. I built tables for users and privileges in an Access database and loaded them to the menu application when the user logged in.

In my application, I made all the functions as UserControls. So in the database, each function had the name of the DLL and the name of the UserControl to call for each specific menu item. Then with the activator class, I loaded the UserControl to a panel in the main form of the application.

In this simple example, I just made a message box for each menu, that says what to do with each menu item based on the information in the database.

The database

The database is very simple: it contains three tables:

  1. USERS
    • Contains username, user ID and password.
  2. ITEMS
    • Contains all menu items - text is the text displayed in the menu and func is the function to call when the item is clicked (it can also be the name of the UserControl, so the Activator can call it to the main panel in the form).
  3. PERMS
    • Contains all permissions for the user.

The code

When the user logs in, the application gets all the information about the user from the database. The code builds two Hashtables to map the items with the respective functions to call when the menu item is clicked. The first Hashtable is called HashMenu and it contains all the information about the menu items that the user can access. Since it is mandatory for the user to also have the parent items the function LoadMenuItems() gets from the database all the items that must be seen, so the user can access the ones he has permission to.

Function LoadMenuItems()
'Load all menu items and sub-items to menu

Dim dsItems As New DataSet
Dim i As Integer

'create a dataset with all items possible
Dim adap As New OleDb.OleDbDataAdapter("", conn)
adap.SelectCommand.CommandText = "SELECT * FROM ITEMS"
adap.Fill(dsItems)

'set the hierarchy as primary key to find 
'the menu item "parents"
dsItems.Tables(0).PrimaryKey = New DataColumn() 
    {dsItems.Tables(0).Columns("HIERAR")}
'go one by one all user items
For i = 0 To dsUser.Tables(0).Rows.Count - 1  
    Dim id_hierar As String 'hierarchy for the item (parents 
                            'and parents parents and so on)
    Dim parent As String 'temp var to store parent index
    
    id_hierar = dsUser.Tables(0).Rows(i)("HIERAR")
    Dim menu_it As New DinamicMenu
    menu_it.Text = dsUser.Tables(0).Rows(i)("TEXT")
    menu_it.Func = dsUser.Tables(0).Rows(i)("FUNC")
    menu_it.MenuItemobj = New MenuItem
    menu_it.MenuItemobj.Text = dsUser.Tables(0).Rows(i)("TEXT")
    AddHandler menu_it.MenuItemobj.Click, AddressOf CallForMenuItem
    If Not HashMenu.ContainsKey(dsUser.Tables(0).Rows(i)("HIERAR")) Then
        HashMenu.Add(dsUser.Tables(0).Rows(i)("HIERAR"), menu_it)
    End If
    While id_hierar.IndexOf(".") > 0
        parent = id_hierar.Substring(0, id_hierar.LastIndexOf("."))
        id_hierar = parent
        Dim dRow As DataRow 'dataRow to store the item row from db
        
        dRow = dsItems.Tables(0).Rows.Find(parent)
        If Not dRow Is Nothing Then
            If Not HashMenu.ContainsKey(parent) Then
                Dim it_dinamic As New DinamicMenu
                it_dinamic.Text = dRow("TEXT")
                it_dinamic.Func = dRow("FUNC")
                it_dinamic.MenuItemobj = New MenuItem
                it_dinamic.MenuItemobj.Text = dRow("TEXT")
                AddHandler it_dinamic.MenuItemobj.Click, _
                                  AddressOf CallForMenuItem
                HashMenu.Add(parent, it_dinamic)
            End If
        End If
    End While
Next

Dim d As DictionaryEntry
Dim parentMenu As New MenuItem
Dim sonMenu As New MenuItem
Dim parentItem As New DinamicMenu
Dim sonItem As New DinamicMenu
Dim sel_key, sel_KeyParent As String

For Each d In HashMenu
    sonItem = d.Value
    sel_key = d.Key
    sonMenu = sonItem.MenuItemobj
    If sel_key.LastIndexOf(".") >= 0 Then
        sel_KeyParent = sel_key.Substring(0, _
                         sel_key.LastIndexOf("."))
        parentItem = HashMenu(sel_KeyParent)
        parentMenu = parentItem.MenuItemobj
        parentMenu.MenuItems.Add(sonMenu)
    Else
        Me.MainMenu.MenuItems.Add(sonMenu)
    End If
Next
CreateHashFunctions()

For each user, the order is different, because they have different permissions, so we have to build a hashtable, called HashFunctions, to create a relation between the place of the item and the item function. There is another function called CallForMenuItem() that executes the function based on the place the menu item was called (since the relation between the place and the function is stored in the hashFunctions Hashtable).

Example

In this simple example, the user logs in as presmad@hotmail.com or presmad@uol.com.br, the password is 1234 for both. These different emails stand for different users. Note that for each user who logs in, the menu is different. If you change the permissions in the database without changing anything in the code, you will see that the new menu from the database applies for the application when you login. The same is valid for creating new users with new menus, of course. Look at the image at the top of this article; note that each user has a different menu when he logs in.

I hope this idea is useful to you, and if you have better ideas about how to built the menu I would be happy to hear from you.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here

About the Author

Daniel Presman
Web Developer
Brazil Brazil
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
QuestionCode in C# versionmemberAndyLPJr29 Feb '12 - 22:09 
Hi Daniel, your code is really great.. I've tried to look around many site but didn't found article like this one.. this really like what I want to develop.. But can you please help me convert this code into c#, cause I'm c# developer n really bad on VB.. Poke tongue | ;-P
 
Regards,
 
Andy.
Generalsomething is missing !memberss_hellhound5 Feb '11 - 8:35 
Thanks Daniel for this job , but it seems we have privilege setting per menu , what if we want to give user the permission per action?
 
suppose we do have a "Customer Management" menu in which the C.R.U.D actions are happening and we want to let user "x" just do the "Create New Customer" action !
GeneralC# versionmemberMember 420593923 Dec '10 - 20:31 
Hi Daniel...
 

i am looking for same example in c#...
do u have it..
i already tried but fell to convert.
my email id is chandravadan_patil@rediffmail.com
GeneralAnother examplesmembermelch211313 Aug '09 - 6:56 
Anybody I can tell me another example dynamic based on databes i will like to compare with anothers examples, i need urgent
GeneralRe: Another examplesmemberDaniel Presman2 Sep '09 - 7:37 
Hi,
 
I really didn't find then, and that's the reason I wrote this code.
But I guess I was not worry about performance or to handle many users.
 
I am sure it is easy to come up with a smarter and faster code.
 
Smile | :) Daniel
GeneralThanks for such a good post!memberkmshelke10 Dec '08 - 23:00 
Hi,
 
Thanks for this code. I have further modified this code to use with MenuStrips and have added column for Shortcut-keys.
Whenever I find time will update the menustrip code along with shortcut key creation.
 
Kuldip
QuestionHow to run code from funcToCall 2memberevilson11 Nov '07 - 3:39 
can you put an example on runing a function on this?
GeneralRe: How to run code from funcToCall 2memberDaniel Presman29 Jan '08 - 3:45 
It is really not so simple. I did not find a better way to do that than to call with the Activator class. Look it up at the MSDN.
 
regards,
 
Daniel
QuestionCalling Form From Dynamic Menumemberabuzy27 Jul '07 - 0:20 
The code looks great and is exactly what I need but I want to able to call a form when the user clicks and option. Great if you can give a code to do that.
 
Thanks,
 
Thomas
Generala note from SirasadminSean Ewington10 Jul '07 - 10:30 
"Dear Mr. Daniel Presman, could you send me the source code of the menu we did, so I am getting trouble to implement your articles. I keep hearing from you."
- Siras

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web04 | 2.6.130523.1 | Last Updated 10 Nov 2005
Article Copyright 2005 by Daniel Presman
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid