views:

250

answers:

2

I have a component I created in C# which had previously been using the default constructor, but now I would like it to have its parent form create the object (in the designer), by passing a reference to itself.

In other words, instead of the following in the designer.cs:

        this.componentInstance = new MyControls.MyComponent();

I would like to instruct the form designer to create the following:

        this.componentInstance = new MyControls.MyComponent(this);

Is it possible to achieve this (preferably through some attribute/annotation or something)?

+2  A: 

Can't you simply use the Control.Parent property? Granted, it will not be set in the constructor of your control, but the typical way to overcome that is by implementing ISupportInitialize and doing the work in the EndInit method.

Why do you need the reference back to the owing control?

Here, if you create a new console application, and paste in this content to replace the contents of Program.cs, and run it, you'll notice that in .EndInit, the Parent property is correctly set.

using System;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;

namespace ConsoleApplication9
{
    public class Form1 : Form
    {
        private UserControl1 uc1;

        public Form1()
        {
            uc1 = new UserControl1();
            uc1.BeginInit();
            uc1.Location = new Point(8, 8);

            Controls.Add(uc1);

            uc1.EndInit();
        }
    }

    public class UserControl1 : UserControl, ISupportInitialize
    {
        public UserControl1()
        {
            Console.Out.WriteLine("Parent in constructor: " + Parent);
        }

        public void BeginInit()
        {
            Console.Out.WriteLine("Parent in BeginInit: " + Parent);
        }

        public void EndInit()
        {
            Console.Out.WriteLine("Parent in EndInit: " + Parent);
        }
    }

    class Program
    {
        [STAThread]
        static void Main()
        {
            Application.Run(new Form1());
        }
    }
}
Lasse V. Karlsen
Thanks, I didn't think to override EndInit() (I haven't done a lot with my own components yet). That's the answer I was looking for.
Dov
A: 

I don't know any way of actually having the designer emit code calling a non-default constructor, but here's an idea to get around it. Put your initialization code inside the default constructor of the parent form and use Form.DesignMode to see if you need to execute it.

public class MyParent : Form
{
    object component;

    MyParent()
    {
        if (this.DesignMode)
        {
            this.component = new MyComponent(this);
        }
    }
}
Ari Roth