/// <summary> /// Removes control from this control. Inheriting controls should call /// base.remove to ensure that the control is removed. /// </summary> public virtual void Remove(Control value) { // Sanity check parameter if (value == null) { return; // Don't do anything } if (value.ParentInternal == Owner) { Debug.Assert(Owner != null); value.SetParentHandle(IntPtr.Zero); // Remove the control from the internal control array // InnerList.Remove(value); value.AssignParent(null); LayoutTransaction.DoLayout(Owner, value, PropertyNames.Parent); Owner.OnControlRemoved(new ControlEventArgs(value)); // ContainerControl needs to see it needs to find a new ActiveControl. if (Owner.GetContainerControl() is ContainerControl cc) { cc.AfterControlRemoved(value, Owner); } } }
public virtual void Add(Control value) { if (value == null) { return; } items.Add(value); value.AssignParent(owner); owner.PerformLayout(); owner.OnControlAdded(new ControlEventArgs(value)); }
/// <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)); }
public virtual void Add(Control value) { items.Add(value); value.AssignParent(owner); }