From fcd43553d112af1ee9553986e811802fbf4f00cb Mon Sep 17 00:00:00 2001 From: Curtis Wensley Date: Tue, 28 May 2024 10:49:47 -0700 Subject: [PATCH] Only remove the child from parent if it is different --- src/Eto/Forms/Container.cs | 20 +++++++++----- .../Forms/Layout/TableLayoutTests.cs | 26 +++++++++++++++++++ 2 files changed, 39 insertions(+), 7 deletions(-) diff --git a/src/Eto/Forms/Container.cs b/src/Eto/Forms/Container.cs index a64b2135f..c372ca696 100755 --- a/src/Eto/Forms/Container.cs +++ b/src/Eto/Forms/Container.cs @@ -363,23 +363,23 @@ protected void SetParent(Control child, Action assign = null, Control previousCh SuspendLayout(); if (Handler is IThemedControlHandler) { - if (!ReferenceEquals(previousChild, null)) + if (previousChild is not null) RemoveLogicalParent(previousChild); - if (!ReferenceEquals(child, null) && ReferenceEquals(child.LogicalParent, null)) + if (child is not null && child.LogicalParent is null) SetLogicalParent(child); assign(); ResumeLayout(); return; } - if (!ReferenceEquals(previousChild, null) && !ReferenceEquals(previousChild, child)) + if (previousChild is not null && !ReferenceEquals(previousChild, child)) { #if DEBUG if (!ReferenceEquals(previousChild.VisualParent, this)) throw new ArgumentException("The previous child control is not a child of this container. Ensure you only remove children that you own."); #endif - if (!ReferenceEquals(previousChild.VisualParent, null)) + if (previousChild.VisualParent is not null) { if (previousChild.Loaded) { @@ -393,15 +393,21 @@ protected void SetParent(Control child, Action assign = null, Control previousCh previousChild.InternalLogicalParent = null; } } - if (!ReferenceEquals(child, null) && !ReferenceEquals(child.VisualParent, this)) + if (child is not null && !ReferenceEquals(child.VisualParent, this)) { // Detach so parent can remove from controls collection if necessary. // prevents UnLoad from being called more than once when containers think a control is still a child // no-op if there is no parent (handled in detach) - child.Detach(); //.VisualParent?.Remove(child); + child.VisualParent?.Remove(child); - if (ReferenceEquals(child.InternalLogicalParent, null)) + // Remove from previous parent only if it differs + if (child.InternalLogicalParent is not null && !ReferenceEquals(child.InternalLogicalParent, this)) + child.InternalLogicalParent?.Remove(child); + + // Set new logical parent + if (child.InternalLogicalParent is null) SetLogicalParent(child); + child.VisualParent = this; if (Loaded && !child.Loaded) { diff --git a/test/Eto.Test/UnitTests/Forms/Layout/TableLayoutTests.cs b/test/Eto.Test/UnitTests/Forms/Layout/TableLayoutTests.cs index c1f58380e..a97e388f8 100644 --- a/test/Eto.Test/UnitTests/Forms/Layout/TableLayoutTests.cs +++ b/test/Eto.Test/UnitTests/Forms/Layout/TableLayoutTests.cs @@ -271,6 +271,32 @@ public void CopyingCellsShouldReparentChildren() return layout2; }); } + + [Test] + public void AddingChildToAnotherPanelShouldRemoveFromTableLayout() + { + Invoke(() => + { + var child = new Label { Text = "I should be shown!" }; + + var layout1 = new TableLayout { ID = "layout1" }; + layout1.Rows.Add(child); + Assert.AreEqual(child.Parent, layout1, "#1.1 Child's parent should now be layout1"); + Assert.AreEqual(child.LogicalParent, layout1, "#1.2 Child's logical parent should now be layout1"); + + // use the child somewheres else + var panel = new Panel { ID = "panel" }; + panel.Content = child; + + Assert.AreEqual(1, layout1.Rows.Count, "#2.1 layout1 should still have a row"); + CollectionAssert.DoesNotContain(layout1.Children, child, "#2.2 Child should no longer be in layout1"); + + Assert.AreEqual(child.Parent, panel, "#2.3 Child's parent should now be panel"); + Assert.AreEqual(child.LogicalParent, panel, "#2.4 Child's logical parent should now be panel"); + CollectionAssert.Contains(panel.Children, child, "#2.5 Child should be in panel"); + }); + } + } }