Creating controls at design time: Error: 'child' is not a child control of this parent

Hello all together,

I am just having a little problem with my custom control and its control designer.

My task:
Writing a control (derived from TableLayoutPanel) which has the following behaviour:

Other developers could select it in the Toolbox of VS.NET and drag it to the form.
Afterwards they can drag other controls (TextBoxes, ListBoxes, etc.) from the Toolbox and drop them into my control. At this time, a control designer should ask the developer to enter a name for a Label, which belongs to the control dropped by the developer. Now, the Designer forces my control to redraw itself.

Redrawing:
The Control should create a specified amount of columns, set by a property. Within each column, a FlowLayoutPanel should host a different amount of TableLayoutPanels (each TableLayoutPanel has two Cells: one for the label at the left side and one for the dropped control on the right side)

Problem:
When I am trying this, I have to remove the dropped control from the controls collection of my written control and put it into the generated TableLayoutPanel (which I have to put into the FlowLayoutPanel etc) . Here I am getting the Error:

'child' is not a child control of this parent

What could this be and how could I resolve it?
Is there any way of a little workaround or so?

I just tried to hook up the ComponentAdding Event of the designer and so preventing the control dropped by the developer (TextBox, etc) from being added to the controls collection of my control, but it doesn't work.
Also resetting the controls parent won't work.

Here's what I have done:

// the current Column, the FlowLayoutPanel should be added to
int cur_Col = 0;

// running through the columns
foreach ( ... ) {

FlowLayoutPanel fP =newFlowLayoutPanel();
fP.Dock = DockStyle.Fill;
fP.BorderStyle = BorderStyle.FixedSingle;

Controls.Add(fP, cur_Col, 0);

// running through the controls for each column
foreach( Control cin ... ) {

// each control is added to a TableLayoutPanel
// This Panel is added to the FlowLayoutPanel

TableLayoutPanel tP =new TableLayoutPanel();
fP.Controls.Add(tP);

// setting the Parent of the control and putting it into
// the controls collection of the TableLayoutPanel

c.Parent = tP;
tP.Controls.Add(c, 1, 0);

Control cLabel =new Label();
cLabel.Text = "some text";
tP.Controls.Add(cLabel, 0, 0);

}

cur_Col++;
}

Regards,
Harald K?stinger
[5889 byte] By [HaraldK?stinger] at [2007-12-21]
# 1
In your sample code, at which line is the error ocuring?
PeterRitchie at 2007-8-30 > top of Msdn Tech,Windows Forms,Windows Forms Designer...
# 2

Hi,

I think that you are hooking the wrong event. ComponentAdding is called before the component is actually hooked up. You might want to look at hooking ComponentAdded.

Martin

MartinThorsen-MSFT at 2007-8-30 > top of Msdn Tech,Windows Forms,Windows Forms Designer...
# 3
Hello,

the error occured when adding the control to the FlowLayoutPanel.

Regards,
Harald K?stinger

HaraldK?stinger at 2007-8-30 > top of Msdn Tech,Windows Forms,Windows Forms Designer...
# 4
Hello all together,

don't know if it is interesting to you or not, but I started a little workaround for that problem.
I always got the error, that the specified control i dropped on my control is not a child of that parent or so.

I "asked" Google for that problem and after days of searching, I found a little helpful post on www.codeproject.com, which helped me very much.

Here's the workaround:
1. When a control is dropped onto my custom control, the designer does not redraw the panel
2. Developers have to right-click on my control and so call the designer to redraw the control
3. Creating controls in code not with a simple new

What I have done:
First, I wrote a new method for redrawing. Here, I try to find a designer host and forces the designer host to create my components --> advantage: the designer host automatically generates the needed designer code in the background.

IDesignerHost host = (IDesignerHost)GetService(typeof(IDesignerHost));
DesignerTransaction dt = null;
IComponentChangeService cService = (IComponentChangeService)GetService(typeof(IComponentChangeService));

// starting the Transaction for creating controls at design time
if (DesignMode && host != null)

dt = host.CreateTransaction("Ausrichten");

...

FlowLayoutPanel fP = null;

// try to find the Panel in the control
if (DesignMode && erneutesAusrichten)
fP = (FlowLayoutPanel)this.GetControlFromPosition(cur_Col, 0);

// when no control is found, try to create it via the host
if (DesignMode && host != null && fP == null)
fP = (FlowLayoutPanel)host.CreateComponent(typeof(FlowLayoutPanel));

// if there was no way before to create the control, create
// it with its own parameterless constructor
else if (fP == null)
fP = new FlowLayoutPanel();

... // adding the dropped controls to the TableLayoutPanels
// and the TableLayoutPanels to the FlowLayoutPanel

// now, a message to the designer and the control is send, that there
//
were some changes in the hierarchy of the controls
if (DesignMode && cService != null)
cService.OnComponentChanging(this, null);

// adding the flow layout panel to my control
Controls.Add(fP, cur_Col, 0);

if (DesignMode && cService != null)
cService.OnComponentChanged(this, null, null, null);


... // setting some properties for the look and feel of the controls

// commit the transaction
if (DesignMode && dt != null)
dt.Commit();


// now invalidate the control
Invalidate();


-

That's what I have done. Now it works fine. The only disadvantage is, that the developer has to right-click and manually forces the control to redraw, but that's not so much work i think.

Anyway, thanks for your help.

Regards,
Harald K?stinger

HaraldK?stinger at 2007-8-30 > top of Msdn Tech,Windows Forms,Windows Forms Designer...