We have a similar implementation at work. This is a pretty straightforward design and works well.
You may want to add a unique identifier to each MenuItem. This can be as simple as:
public enum MenuItems
{
File_New = 100,
File_Save = 110,
// ...
}
And you include this number in the database. Then, when you write out the menu items, you can have a dictionary that maps the MenuItems integer to a delegate (for handling the execute event):
delegate void MenuItemExecuteHandler();
IDictionary<int, MenuItemExecuteHandler> MenuItemHandlers;
And somewhere define the mappings:
MenuItemHandlers.Add(MenuItems.File_New, this.OnFileNewClick());
So that when you hookup the menu item event handlers, you can call the right method to perform the right action:
int id = 100; // Retrieved from the database.
MenuItems menuItem = (MenuItems)Enum.TryParse(typeof(MenuItems), id);
string command = "..."; // Retrieved from the database using the MenuItem ID.
MenuItemControl control = new MenuItemControl();
control.Text = command;
control.OnClick += new EventHandler(delegate (object sender, EventArgs args)
{
MenuItemHandlers[menuItem].Invoke();
});
(Something to that effect, I probably have the syntax off slightly)
Update:
The "Tag" property of the tree-view item control gets populated like this, following the example above:
TreeItemControl control = new TreeItemControl();
control.Text = "New File"; // Retrieved from database.
control.Tag = 100; // Retrieved from database.
Then, when looking for what to write out:
if (control.CheckState = CheckState.Checked)
{
row["MenuItemID"] = control.Tag;
row["Allowed"] = true;
}