0

I have 3 folders which contains a bunch of subfolders and files. I need to create a ContextMenuStrip with all the folders and files as ToolStripMenuItems (as a tree hierarchy). I know how to hardcode it:

    public class CustomApplicationContext : ApplicationContext
    {
        private NotifyIcon trayIcon;
        private ContextMenuStrip contextMenuStrip = new ContextMenuStrip();
        ToolStripMenuItem option1 = new ToolStripMenuItem("Option 1");
        ToolStripMenuItem option1a = new ToolStripMenuItem("Option 1a");
        ToolStripMenuItem option1b = new ToolStripMenuItem("Option 1b");
        ToolStripMenuItem option1c = new ToolStripMenuItem("Option 1c");
        ToolStripMenuItem option1ca = new ToolStripMenuItem("Option 1ca");
        ToolStripMenuItem option2 = new ToolStripMenuItem("Option 2");
        ToolStripMenuItem option3 = new ToolStripMenuItem("Option 3");
        ToolStripMenuItem option4 = new ToolStripMenuItem("Option 4");

        public CustomApplicationContext()
        {
            contextMenuStrip.Items.AddRange(new ToolStripItem[]
            {
                this.option1,
                this.option2,
                this.option3,
                this.option4
            });
            this.option1.DropDownItems.AddRange(new ToolStripItem[]
            {
                this.option1a,
                this.option1b,
                this.option1c
            });
            this.option1c.DropDownItems.AddRange(new ToolStripItem[] 
            {
                this.option1ca
            });
            trayIcon = new NotifyIcon()
            {
                Icon = Resources.AppIcon,
                ContextMenuStrip = contextMenuStrip,
                Visible = true
            };
        }
    }

However, I would like to make it more dynamically so if something change within one of the folders, it'll also be dynamically changed.

How would I be able to do that?

Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
wads
  • 123
  • 11
  • The same way you added ToolStripMenuItems in your example code? – Robert Harvey Dec 12 '22 at 13:03
  • That isn't really helpful. I am not able or aware on how to do it and saying I need to do it in the same way, doesn't really explain anything. I'm sorry, if this is something easily done for you, but I am still very new to programming. – wads Dec 12 '22 at 13:11
  • Can you provide a more specific example of what you want to do? "Make it more dynamically" can mean many things. – Robert Harvey Dec 12 '22 at 13:15
  • Essentially, the 3 parentfolders contain multiple folders and .pdf files. I need to make a tree of all the folders, subfolders and files. For every folder and it's subfolder need to be a branch in the ContextMenuStrip. The reason to making it dynamic is that if someone adds a new folder or file, I want it to add it to the ContextMenu. – wads Dec 12 '22 at 13:19
  • Are you sure you don't want to use a [TreeView](https://stackoverflow.com/questions/6239544/populate-treeview-with-file-system-directory-structure) for this? – Robert Harvey Dec 12 '22 at 13:21
  • That might well be a better way to go about it. Is it something that can be added to a NotifyIcon? The reason being, that the menu has to running via the NotifyIcon – wads Dec 12 '22 at 13:23
  • You want to put a folder listing in the tray? – Robert Harvey Dec 12 '22 at 13:28
  • Have a look here: https://stackoverflow.com/q/36136833 – Robert Harvey Dec 12 '22 at 13:30
  • Yes, I need to use tray - I'll have a look at the post you've linked. Thank you – wads Dec 12 '22 at 13:52
  • 2
    @RobertHarvey, I use this technique for my help menus. This enables the users to add their own manuals and usage notes. The directory tree for these documents is always kept small. – Olivier Jacot-Descombes Dec 12 '22 at 16:39

1 Answers1

2

It can be done with a recursive method that iterates through a directory tree recursively.

private static void AddMenuItemsRecusively(
    DirectoryInfo root, 
    ToolStripItemCollection itemCollection)
{
    FileInfo[] files = root.GetFiles("*.*");
    if (files != null) {
        foreach (FileInfo fi in files) {
            itemCollection.Add(new ToolStripMenuItem(fi.Name));
        }

        DirectoryInfo[] subDirs = root.GetDirectories();
        foreach (DirectoryInfo dirInfo in subDirs) {
            var menuItem = new ToolStripMenuItem(dirInfo.Name);
            itemCollection.Add(menuItem);
            AddMenuItemsRecusively(dirInfo, menuItem.DropDownItems);
        }
    }
}

Since we must be able to add menu items to a ContextMenuStrip.Items as well as to ToolStripMenuItem.DropDownItems, we pass a ToolStripItemCollection to the method.

We create the menu structure like this with baseDir as DirectoryInfo containing the base directory.

AddMenuItemsRecusively(baseDir, contextMenuStrip.Items);

Call contextMenuStrip.Items.Clear(); before adding the menu items if you want to populate the context menu repeatedly.

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
  • Thanks for the answer. It does exactly what I want! So when you call the `AddMenuItemsRecusively(dirInfo, menuItem.DropDownItems);` within the method, is that what make it recurse through the folders? – wads Dec 12 '22 at 14:14
  • 1
    Yes, the `AddMenuItemsRecusively` method calls itself with a new `DirectoryInfo` corresponding to a sub-directory and a new `ToolStripItemCollection` corresponding to a sub-menu and repeats calling itself until there are no more sub-directories in the current sub-directory. [Debug this code](https://learn.microsoft.com/en-us/visualstudio/get-started/csharp/tutorial-debugger?view=vs-2022) and single step through it to see what happens. Search for [c# recursion](https://www.google.com/search?q=c%23+recursion) to find more about this technique. – Olivier Jacot-Descombes Dec 12 '22 at 14:25