diff --git a/src/Avalonia.Controls/ItemsControl.cs b/src/Avalonia.Controls/ItemsControl.cs index 94c34b28d6..4a4daa31f9 100644 --- a/src/Avalonia.Controls/ItemsControl.cs +++ b/src/Avalonia.Controls/ItemsControl.cs @@ -236,25 +236,7 @@ namespace Avalonia.Controls // it was added to the Items collection. if (container.ContainerControl != null && container.ContainerControl != container.Item) { - if (ItemContainerGenerator.ContainerType == null) - { - var containerControl = container.ContainerControl as ContentPresenter; - - if (containerControl != null) - { - ((ISetLogicalParent)containerControl).SetParent(this); - containerControl.UpdateChild(); - - if (containerControl.Child != null) - { - LogicalChildren.Add(containerControl.Child); - } - } - } - else - { - LogicalChildren.Add(container.ContainerControl); - } + LogicalChildren.Add(container.ContainerControl); } } } @@ -272,24 +254,7 @@ namespace Avalonia.Controls // when it is removed from the Items collection. if (container?.ContainerControl != container?.Item) { - if (ItemContainerGenerator.ContainerType == null) - { - var containerControl = container.ContainerControl as ContentPresenter; - - if (containerControl != null) - { - ((ISetLogicalParent)containerControl).SetParent(null); - - if (containerControl.Child != null) - { - LogicalChildren.Remove(containerControl.Child); - } - } - } - else - { - LogicalChildren.Remove(container.ContainerControl); - } + LogicalChildren.Remove(container.ContainerControl); } } } diff --git a/tests/Avalonia.Controls.UnitTests/CarouselTests.cs b/tests/Avalonia.Controls.UnitTests/CarouselTests.cs index b16ac6bb8e..1bcae8e736 100644 --- a/tests/Avalonia.Controls.UnitTests/CarouselTests.cs +++ b/tests/Avalonia.Controls.UnitTests/CarouselTests.cs @@ -51,10 +51,9 @@ namespace Avalonia.Controls.UnitTests Assert.Single(target.GetLogicalChildren()); - var child = target.GetLogicalChildren().Single(); + var child = GetContainerTextBlock(target.GetLogicalChildren().Single()); - Assert.IsType(child); - Assert.Equal("Foo", ((TextBlock)child).Text); + Assert.Equal("Foo", child.Text); } [Fact] @@ -98,20 +97,18 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(3, target.GetLogicalChildren().Count()); - var child = target.GetLogicalChildren().First(); + var child = GetContainerTextBlock(target.GetLogicalChildren().First()); - Assert.IsType(child); - Assert.Equal("Foo", ((TextBlock)child).Text); + Assert.Equal("Foo", child.Text); var newItems = items.ToList(); newItems.RemoveAt(0); target.Items = newItems; - child = target.GetLogicalChildren().First(); + child = GetContainerTextBlock(target.GetLogicalChildren().First()); - Assert.IsType(child); - Assert.Equal("Bar", ((TextBlock)child).Text); + Assert.Equal("Bar", child.Text); } [Fact] @@ -136,20 +133,18 @@ namespace Avalonia.Controls.UnitTests Assert.Single(target.GetLogicalChildren()); - var child = target.GetLogicalChildren().Single(); + var child = GetContainerTextBlock(target.GetLogicalChildren().Single()); - Assert.IsType(child); - Assert.Equal("Foo", ((TextBlock)child).Text); + Assert.Equal("Foo", child.Text); var newItems = items.ToList(); newItems.RemoveAt(0); target.Items = newItems; - child = target.GetLogicalChildren().Single(); + child = GetContainerTextBlock(target.GetLogicalChildren().Single()); - Assert.IsType(child); - Assert.Equal("Bar", ((TextBlock)child).Text); + Assert.Equal("Bar", child.Text); } [Fact] @@ -197,10 +192,9 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(3, target.GetLogicalChildren().Count()); - var child = target.GetLogicalChildren().First(); + var child = GetContainerTextBlock(target.GetLogicalChildren().First()); - Assert.IsType(child); - Assert.Equal("Foo", ((TextBlock)child).Text); + Assert.Equal("Foo", child.Text); target.Items = null; @@ -233,7 +227,7 @@ namespace Avalonia.Controls.UnitTests Assert.Equal("FooBar", target.SelectedItem); - var child = target.GetVisualDescendants().LastOrDefault(); + var child = GetContainerTextBlock(target.GetVisualDescendants().LastOrDefault()); Assert.IsType(child); Assert.Equal("FooBar", ((TextBlock)child).Text); @@ -261,14 +255,13 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(3, target.GetLogicalChildren().Count()); - var child = target.GetLogicalChildren().First(); + var child = GetContainerTextBlock(target.GetLogicalChildren().First()); - Assert.IsType(child); - Assert.Equal("Foo", ((TextBlock)child).Text); + Assert.Equal("Foo", child.Text); items.RemoveAt(0); - child = target.GetLogicalChildren().First(); + child = GetContainerTextBlock(target.GetLogicalChildren().First()); Assert.IsType(child); Assert.Equal("Bar", ((TextBlock)child).Text); @@ -314,5 +307,12 @@ namespace Avalonia.Controls.UnitTests [~CarouselPresenter.PageTransitionProperty] = control[~Carousel.PageTransitionProperty], }.RegisterInNameScope(scope); } + + private static TextBlock GetContainerTextBlock(object control) + { + var contentPresenter = Assert.IsType(control); + contentPresenter.UpdateChild(); + return Assert.IsType(contentPresenter.Child); + } } } diff --git a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs index 227d783874..a728500316 100644 --- a/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs +++ b/tests/Avalonia.Controls.UnitTests/ItemsControlTests.cs @@ -66,7 +66,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void Container_Child_Should_Have_LogicalParent_Set_To_Container() + public void Container_Should_Have_LogicalParent_Set_To_ItemsControl() { using (UnitTestApplication.Start(TestServices.StyledWindow)) { @@ -87,7 +87,7 @@ namespace Avalonia.Controls.UnitTests var container = (ContentPresenter)target.Presenter.Panel.Children[0]; - Assert.Equal(container, container.Child.Parent); + Assert.Equal(target, container.Parent); } } @@ -190,7 +190,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void Adding_String_Item_Should_Make_TextBlock_Appear_In_LogicalChildren() + public void Adding_String_Item_Should_Make_ContentPresenter_Appear_In_LogicalChildren() { var target = new ItemsControl(); var child = new Control(); @@ -202,7 +202,7 @@ namespace Avalonia.Controls.UnitTests var logical = (ILogical)target; Assert.Equal(1, logical.LogicalChildren.Count); - Assert.IsType(logical.LogicalChildren[0]); + Assert.IsType(logical.LogicalChildren[0]); } [Fact] @@ -575,6 +575,30 @@ namespace Avalonia.Controls.UnitTests }; } + [Fact] + public void Detaching_Then_Reattaching_To_Logical_Tree_Twice_Does_Not_Throw() + { + // # Issue 3487 + var target = new ItemsControl + { + Template = GetTemplate(), + Items = new[] { "foo", "bar" }, + ItemTemplate = new FuncDataTemplate((_, __) => new Canvas()), + }; + + var root = new TestRoot(target); + root.Measure(Size.Infinity); + root.Arrange(new Rect(root.DesiredSize)); + + root.Child = null; + root.Child = target; + + target.Measure(Size.Infinity); + + root.Child = null; + root.Child = target; + } + private class Item { public Item(string value)