How to get a (non-visual) ComponentModel.Component’s parent Form or Control

By admin - Last updated: Friday, March 7, 2008 - Save & Share - One Comment

I recently ran into the need to get the reference of the parent form of a Component that I was creating. The problem is that Components, unlike Controls, don’t have a Parent property, nor any other simple way of getting it. I’ve browsed around for solutions, but I could only find vague references to what needed to be done. Most solutions simply suggested that I simply create a public property, that I then set manually in the parent Control. One article came close, but it didn’t work. It did however point me towards looking into the ErrorProvider component, which does exactly this.

I found the solution by looking through it’s source code. We still expose a public property, however, instead of setting it manually, we can simply instruct Visual Studio to set the property for us, when it generates the designer code for any component we put it into.

private ContainerControl parentControl;
public ContainerControl ParentControl
{
    get { return parentControl; }
    set { parentControl = value; }
}
 
public override ISite Site
{
    set
    {
        base.Site = value;
        if (value == null)
            return;
 
        IDesignerHost host = (IDesignerHost)value.GetService( typeof( IDesignerHost ) );
        if (host != null)
        {
            IComponent baseComp = host.RootComponent;
 
            if (baseComp is ContainerControl)
                this.ContainerControl = (ContainerControl)baseComp;
        }
    }
}

We’re overriding the Site property, so that we can intercept it’s ISite, which will be set when the Component is added to its container. We can then request its IDesignerHost service, which is an interface used to communicate during design time with an aware IDE, such as Visual Studio. We then save it in our public property, which Visual Studio will then automatically add to the generated code of any Control that you drop the component in:

/// 
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// 
private void InitializeComponent()
{
    this.components = new System.ComponentModel.Container();
    this.decorator = new Sunstorm.Tests.FormDecorator( this.components );
    this.SuspendLayout();
    //
    // decorator
    //
    this.decorator.ContainerControl = this;
    //
    // TestForm
    //
    this.Name = "TestForm";
    this.Size = new System.Drawing.Size( 510, 339 );
    this.ResumeLayout( false );
}

From there, you can manipulate the parent in any way you want.

Posted in C# • Tags: , Top Of Page

One Response to “How to get a (non-visual) ComponentModel.Component’s parent Form or Control”

Comment from David Meredith
Time February 24, 2010 at 9:40 pm

Hello,

Instead of
this.ContainerControl = (ContainerControl)baseComp;
should it say,
this.ParentControl = (ContainerControl)baseComp;
?

That is what worked for me. Otherwise, this is EXACTLY what I was looking for, and it came up first in the Google search!

I’m using it to change the title based on certain parameters (certain controls will change different parts of the title), and most of the controls are added using the Composite Application Library, so they are not all aware of each other. Thanks so much!

David

Write a comment

Currently you have JavaScript disabled. In order to post comments, please make sure JavaScript and Cookies are enabled, and reload the page. Click here for instructions on how to enable JavaScript in your browser.