I have a non-visual component which manages other visual controls.
I need to have a reference to the form that the component is operating on, but i don't know how to get it.
I am unsure of adding a constructor with the parent specified as control, as i want the component to work by just being dropped into the designer.
The other thought i had was to have a Property of parent as a control, with the default value as 'Me'
any suggestions would be great
Edit:
To clarify, this is a component, not a control, see here :ComponentModel.Component
[It is important to understand that the ISite technique below only works at design time. Because ContainerControl is public and gets assigned a value VisualStudio will write initialization code that sets it at run-time. Site is set at run-time, but you can't get ContainerControl from it]
Here's an article that describes how to do it for a non-visual component.
Basically you need to add a property ContainerControl to your component:
public ContainerControl ContainerControl { get { return _containerControl; } set { _containerControl = value; } } private ContainerControl _containerControl = null;
and override the Site property:
public override ISite Site { get { return base.Site; } set { base.Site = value; if (value == null) { return; } IDesignerHost host = value.GetService( typeof(IDesignerHost)) as IDesignerHost; if (host != null) { IComponent componentHost = host.RootComponent; if (componentHost is ContainerControl) { ContainerControl = componentHost as ContainerControl; } } } }
If you do this, the ContainerControl will be initialized to reference the containing form by the designer. The linked article explains it in more detail.
A good way to see how to do things is to look at the implementation of Types in the .NET Framework that have behaviour similar to what you want with a tool such as Lutz Reflector. In this case, System.Windows.Forms.ErrorProvider is a good example to look at: a Component that needs to know its containing Form.
I use a recursive call to walk up the control chain. Add this to your control.
public Form ParentForm { get { return GetParentForm( this.Parent ); } } private Form GetParentForm( Control parent ) { Form form = parent as Form; if ( form != null ) { return form; } if ( parent != null ) { // Walk up the control hierarchy return GetParentForm( parent.Parent ); } return null; // Control is not on a Form }
Edit: I see you modified your question as I was typing this. If it is a component, the constructor of that component should take it's parent as a parameter and the parent should pass in this when constructed. Several other components do this such as the timer.
Save the parent control as a member and then use it in the ParentForm property I gave you above instead of this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With