/// <summary>
/// Adds a child control to this control. The control becomes the last control in
/// the child control list. If the control is already a child of another control it
/// is first removed from that control.
/// </summary>
public virtual void Add(Control value)
{
if (value == null)
{
return;
}
if (value.GetTopLevel())
{
throw new ArgumentException(SR.TopLevelControlAdd);
}
// Verify that the control being added is on the same thread as
// us...or our parent chain.
if (Owner.CreateThreadId != value.CreateThreadId)
{
throw new ArgumentException(SR.AddDifferentThreads);
}
CheckParentingCycle(Owner, value);
if (value._parent == Owner)
{
value.SendToBack();
return;
}
// Remove the new control from its old parent (if any)
if (value._parent != null)
{
value._parent.Controls.Remove(value);
}
// Add the control
InnerList.Add(value);
if (value._tabIndex == -1)
{
// Find the next highest tab index
int nextTabIndex = 0;
for (int c = 0; c < (Count - 1); c++)
{
int t = this[c].TabIndex;
if (nextTabIndex <= t)
{
nextTabIndex = t + 1;
}
}
value._tabIndex = nextTabIndex;
}
// if we don't suspend layout, AssignParent will indirectly trigger a layout event
// before we're ready (AssignParent will fire a PropertyChangedEvent("Visible"), which calls PerformLayout)
#if DEBUG
int dbgLayoutCheck = Owner.LayoutSuspendCount;
#endif
Owner.SuspendLayout();
try
{
Control oldParent = value._parent;
try
{
// AssignParent calls into user code - this could throw, which
// would make us short-circuit the rest of the reparenting logic.
// you could end up with a control half reparented.
value.AssignParent(Owner);
}
finally
{
if (oldParent != value._parent && (Owner._state & STATE_CREATED) != 0)
{
value.SetParentHandle(Owner.InternalHandle);
if (value.Visible)
{
value.CreateControl();
}
}
}
value.InitLayout();
}
finally
{
Owner.ResumeLayout(false);
#if DEBUG
Owner.AssertLayoutSuspendCount(dbgLayoutCheck);
#endif
}
// Not putting in the finally block, as it would eat the original
// exception thrown from AssignParent if the following throws an exception.
LayoutTransaction.DoLayout(Owner, value, PropertyNames.Parent);
Owner.OnControlAdded(new ControlEventArgs(value));
}