Creating nested menus programmatically

Aug 23, 2011 at 8:48 PM

I'm a bit lost with the API, how would you programmatically write a method that dynamically constructs a menu? Perhaps, it's worth to create a helper method that would do just that?

PopupMenuItem AddMenu(params string[] captions)

Usage:

var menu = new PopupMenu();
menu.AddMenu("File", "Open", "Project").Click += (_, __) => OpenProject():
menu.AddMenu("File", "Open", "File").Click += (_, __) => OpenFile():

Coordinator
Aug 24, 2011 at 7:26 PM
Edited Aug 24, 2011 at 8:21 PM

Have you tried the demo code? It contains a few examples showing how to do this.

There is no method that takes only an array of strings for the menu hierarchy since that would be an oversimplistic approach IMO since in most cases one would not want to add just captions but icons and other stuff as well.

The AddSubMenu function(see basic usage on homepage) is quite convenient for this and comes with many overloads. However you can easily add your own helper for this based on the existing API.

Aug 24, 2011 at 7:37 PM

The problem I faced was inspecting the existing menu and finding out which of the existing items are actually ParentBarItems and properly adding sub-menus to existing sub-menus. I wrote similar methods for other (WinForms-based) popup menus in matters of minutes, but gave up on SL4PM. I guess I'll give it another try...

My opinion is that it would have been an over-simplistic approach had it been the only way to work with it, but it makes total sense to have that super-simple method for constructing a menu with one line of code; I'm sure that many people need just that. Just my $.02 :)

Coordinator
Aug 25, 2011 at 12:46 AM
Edited Aug 27, 2011 at 12:41 AM

Hmmm...I agree with you Skalkin. You point is perfectly valid but I can't help asking myself what if the user wants to further customize his menu later on? Would it be ok that he might have to completely rewrite his existing code just to do that? If not how would I go about making this customization friendly?... As you can see its not as simple as it seems to implement and unfortunately customizability and simplicity don't go hand in hand here. Nevertherless I'll definitely give it a thought in my free time and let you know if I come up with something.

As for the existing implementation I guess that much of the confusion lies in the fact that SL4PM does not provide any toolbar as such but the good news is that you are free to use any control for this. So if your toolbar is a ListBox you need to attach each menu to the corresponding ListBoxItem using the AddTrigger method.

Assuming you already created a ListBox containing an item named File, here's how you can implement a menu based on the code you mentioned above:

var mnuFile = new PopupMenu();
mnuFile.AddTrigger(TriggerTypes.LeftClick, File);

var mnuOpen = new PopupMenu();
mnuOpen.AddItem("Project", (_, __) => { OpenProject(); });
mnuOpen.AddItem("File", (_, __) => { OpenFile(); });

mnuFile.AddSubMenu(mnuOpen, "Open", null, null, null, false, null);

However if you need to visually organize the subitem generation code you can group it within the Opening event of its parent menu as shown below:

var mnuFile = new PopupMenu();
mnuFile.Closing += delegate{ mnuFile.Items.Clear(); };
mnuFile.AddTrigger(TriggerTypes.LeftClick, File);

mnuFile.Opening += delegate 
{
    var mnuOpen = new PopupMenu();
    mnuFile.AddSubMenu(mnuOpen, "Open", null, null, null, false, null);
    mnuOpen.AddItem("Project", (_, __) => { OpenProject(); });
    mnuOpen.AddItem("File", (_, __) => { OpenFile(); });
};

I recommend switching to XAML for hard coded menus like those however and only get back to the C# API for dynamic implementations that XAML fails to address.