I’ve got some code that will generically get all Controls in a form and put them in a list. Here’s some of the code:
private List<Control> GetControlList(Form parentForm) { List<Control> controlList = new List<Control>(); AddControlsToList(parentForm.Controls, controlList); return controlList; } private void AddControlsToList(Control.ControlCollection rootControls, List<Control> controlList) { foreach (Control c in rootControls) { controlList.Add(c); if (c.HasChildren) AddControlsToList(c.Controls, controlList); // } }
So I’m only able to use c.HasChildren to check and see if there’s any more child controls from this root control.
What about a menuStrip, toolStrip, and statusStrip? How do I get all of the controls that are in these controls generically? Ex: MenuStripItem
I know that I could try testing the c.GetType() == typeof(MenuStrip) but I was hoping to not have to do specific type tests.
If I need to give more info, please ask.
Thanks a bunch
I believe the VS designer does it by getting an instance of the control’s designer (see the
Designerattribute), and, if the designer is aComponentDesigner, getting theAssociatedComponentsproperty.EDIT:
Okay, I guess that’s a little vague. A warning, though: what follows is a little complicated, and might not be worth the effort.
A note on nomenclature:
Below, I will be referring to both the designer within Visual Studio—which is the name used to refer to the functionality within Visual Studio by which the layout and content of forms and controls are edited visually—and to designer classes—which will be explained below. To prevent confusion as to which I am referring to at any given time, I will always refer to the designer functionality within Visual Studio as ‘the designer’, and I will always refer to a designer class as an ‘IDesigner’, which is the interface each must implement.
When the Visual Studio designer loads a component (usually a control, but also things like
Timerand such), it looks for a custom attribute on the class of typeDesignerAttribute. (Those unfamiliar with attributes might want read up on them before continuing.)This attribute, if present, provides the name of a class—an IDesigner—the designer can use to interface with the component. In effect, this class controls certain aspects of the designer and of the design-time behavior of the component. There’s indeed quite a lot you can do with an IDesigner, but right now we’re only interested in one thing.
Most controls that use a custom IDesigner use one that derives from
ControlDesigner, which itself derives fromComponentDesigner. TheComponentDesignerclass has a public virtual property calledAssociatedComponents, which is meant to be overridden in derived classes to return a collection of references to all ‘child’ components of this one.To be more specific, the
ToolStripcontrol (and by inheritance, theMenuStripcontrol) has aDesignerAttributethat references a class calledToolStripDesigner. It looks sort of like:The
ToolStripDesignerclass is not public. It’s internal to System.Design.dll. But since it’s specified here by it’s fully qualified name, the VS designer can useActivator.CreateInstanceto create an instance of it anyway.This
ToolStripDesignerclass, because it inherits [indirectly] fromComponentDesignerhas anAssociatedComponentsproperty. When you call it you get a newArrayListthat contains references to all the items that have been added to theToolStrip.So what would your code have to look like to do the same thing? Rather convoluted, but I think I have a working example: