6

Currently I have most of my form's controls disabled at launch because you cannot use them until a file is loaded. However, once the file is loaded the controls should become enabled.

I was using bindings but I don't think they're a good solution. For one, it is unnecessary complexity. Secondly, you cannot use bindings for everything. For example, MenuStrip items cannot have their Enabled property bound to the fileLoaded property. Only the entire menu can and I don't want to disable the entire menu at launch, only certain menu operations that operate on the file.

I'm really just looking for a way to enable EVERYTHING. Most when asked that would answer with this:

foreach (Control c in Controls)
{
    c.Enabled = true;
}

However, that does not work for enabling MenuStrip items or controls within other controls (like a Panel or custom control). Therefore it would not enable scrollbars within containers.

I suppose I could use that line and manually enable everything else but I could have always just manually enabled everything. I'm looking for a way to automatically enable everything.

John Smith
  • 8,567
  • 13
  • 51
  • 74
  • How were those elements disabled in the first place? Maybe you can keep track of what got disabled in a list and then re-enable all elements from that list (and clear it). – Philipp Schmid Aug 24 '11 at 22:09
  • They are disabled in the form designer. Most of the application's tools cannot be used without a loaded file so they are disabled by default. – John Smith Aug 24 '11 at 22:26

5 Answers5

12

Recursion

private void enableControls(Control.ControlCollection Controls)
{
    foreach (Control c in Controls)
    {
        c.Enabled = true;
        if (c is MenuStrip)
        {
           foreach(var item in ((MenuStrip)c).Items)
           { 
              item.Enabled = true;
           }
        }
        if (c.ControlCollection.Count > 0)
            enableControls(c.Controls);

    }
}

Edit

Should have been checking the control Collection count instead of HasControls Which is Webcontrols

msarchet
  • 15,104
  • 2
  • 43
  • 66
  • Thanks, this works well. However, it still does not enable MenuStrip items. I suppose I could manually enable them but I wonder if there is a way to include them with this loop? – John Smith Aug 24 '11 at 22:25
  • 1
    Still doesn't work =P Through debugging I found it is only enabling the button and not the sub-menu. For example, if you have menu items File and Edit it would only enable those two and not the menu items New, Save, Undo, and Redo. Also, item has to be casted to ToolStripMenuItem and c.ControlCollection.Count > 0 should be replaced with c.HasChildren. – John Smith Aug 24 '11 at 22:36
  • This works: http://pastebin.com/dYmyunaV But it may be a bit overkill or unnecessary if there is a better way. – John Smith Aug 24 '11 at 22:48
  • Not to long rather than to have all controls in a panel ? to enable/disable a panel is only a line of code. – icaptan Aug 25 '11 at 12:11
6

Put all controls in a panel;

panel.enable = false -> all controls in the panel will be disabled panel.enable = true -> all controls in the panel will be enabled (if they are in default enabled, shortly fill your panel with enabled controls, let your panel disabled so that your controls will be disabled, too. After enabling panel, your controls will be enabled )

icaptan
  • 1,495
  • 1
  • 16
  • 36
3

For menustrip items you can do it recursively, it's very simple. Just set the item.Enabled Flag to true or false.

You can use my class, it's just a few lines code, easy to use. You can also create a Search Function and just pass the name want to disable. Enjoy:

namespace Test_MenuItemIteration
{
    using System.Collections.Generic;
    using System.Windows.Forms;

    public static class GetAllMenuStripItems
    {
        #region Methods

        /// <summary>
        /// Gets a list of all ToolStripMenuItems
        /// </summary>
        /// <param name="menuStrip">The menu strip control</param>
        /// <returns>List of all ToolStripMenuItems</returns>
        public static List<ToolStripMenuItem> GetItems(MenuStrip menuStrip)
        {
            List<ToolStripMenuItem> myItems = new List<ToolStripMenuItem>();
            foreach (ToolStripMenuItem i in menuStrip.Items)
            {
                GetMenuItems(i, myItems);
            }
            return myItems;
        }

        /// <summary>
        /// Gets the menu items.
        /// </summary>
        /// <param name="item">The item.</param>
        /// <param name="items">The items.</param>
        private static void GetMenuItems(ToolStripMenuItem item, List<ToolStripMenuItem> items)
        {
            items.Add(item);
            foreach (ToolStripItem i in item.DropDownItems)
            {
                if (i is ToolStripMenuItem)
                {
                    GetMenuItems((ToolStripMenuItem)i, items);
                }
            }
        }

        #endregion Methods
    }
}

Use in your app:

List<ToolStripMenuItem> myItems = GetAllMenuStripItems.GetItems(this.menuStrip1);
foreach (var item in myItems)
{
    MessageBox.Show(item.Text);
    item.Enabled = false;
}
Flexo
  • 87,323
  • 22
  • 191
  • 272
Stefan0410
  • 121
  • 1
  • 2
2

Do this:

var Enable = (Control c) =>
             {
                 c.Enabled = true;
                 if(c.Controls != null)
                     foreach(Control c2 in c.Controls)
                         Enable(c2);
             }

Enable(YourForm);
Daniel
  • 30,896
  • 18
  • 85
  • 139
  • @msarchet: no it doesn't, its recursive – Daniel Aug 24 '11 at 23:19
  • This one is fine. Just remember that it will look for ALL controls. Might be interesting to filter them. The Tag property might help. For instance, when Tag != null you check for the control itself and all owned controls, if not, just skip. – Anderson Matos Aug 25 '11 at 14:29
  • Why do you need `if(c.Controls != null)` ? in case it is null the `foreach` will not do anything – Rafael Herscovici Jun 05 '15 at 08:15
1

Recursively iterating over your menu is necessary to Disable every item in your menus. However, there is a simpler solution for all of your form controls-- embed them in a panel that spans across the entire form and disable the form in the VS Designer. When your user selects a file, enable the Panel and viola! No extra recursion (or overhead) necessary.

If you still want to go the recursive route, I would change the Enable method by first renaming it to ChangeEnabledState and, second, I would a a bool parameter that would allow you use to assign to the Enabled property. That way you can enable/disable the controls as necessary. Remember, however, you will need to add a check to see if the control is the button (or what ever control you are using to open the OpenFileDialog) is skipped in a disable operation.

RLH
  • 15,230
  • 22
  • 98
  • 182