From 7251c72d32908bd588170e2ddda9fab31cb69ddd Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 16 Oct 2019 11:08:15 +0200 Subject: [PATCH] Merge pull request #3118 from AvaloniaUI/fixes/3115-visualnode-disposed Add VisualNode to scene even for invisible controls --- .../Rendering/SceneGraph/SceneBuilder.cs | 4 ++ .../Rendering/SceneGraph/VisualNode.cs | 2 +- .../Rendering/SceneGraph/SceneBuilderTests.cs | 53 +++++++++++++++++++ .../Rendering/SceneGraph/VisualNodeTests.cs | 19 +++++++ 4 files changed, 77 insertions(+), 1 deletion(-) diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs index 161cbc099e..87c9ed0bae 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/SceneBuilder.cs @@ -240,6 +240,10 @@ namespace Avalonia.Rendering.SceneGraph } } } + else + { + contextImpl.BeginUpdate(node).Dispose(); + } } private void UpdateSize(Scene scene) diff --git a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs index f579bf0a62..d342f2eb2e 100644 --- a/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs +++ b/src/Avalonia.Visuals/Rendering/SceneGraph/VisualNode.cs @@ -218,7 +218,7 @@ namespace Avalonia.Rendering.SceneGraph if (first < _children?.Count) { EnsureChildrenCreated(); - for (int i = first; i < _children.Count - first; i++) + for (int i = first; i < _children.Count; i++) { _children[i].Dispose(); } diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs index 13bcd27240..5fd14e9ea9 100644 --- a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/SceneBuilderTests.cs @@ -577,6 +577,59 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph } } + [Fact] + public void Should_Not_Dispose_Active_VisualNode_When_Control_Reparented_And_Child_Made_Invisible() + { + // Issue #3115 + using (UnitTestApplication.Start(TestServices.MockPlatformRenderInterface)) + { + StackPanel panel; + Border border1; + Border border2; + var tree = new TestRoot + { + Width = 100, + Height = 100, + Child = panel = new StackPanel + { + Children = + { + (border1 = new Border + { + Background = Brushes.Red, + }), + (border2 = new Border + { + Background = Brushes.Green, + }), + } + } + }; + + tree.Measure(Size.Infinity); + tree.Arrange(new Rect(tree.DesiredSize)); + + var scene = new Scene(tree); + var sceneBuilder = new SceneBuilder(); + sceneBuilder.UpdateAll(scene); + + var decorator = new Decorator(); + tree.Child = null; + decorator.Child = panel; + tree.Child = decorator; + border1.IsVisible = false; + + scene = scene.CloneScene(); + + var panelNode = (VisualNode)scene.FindNode(panel); + sceneBuilder.Update(scene, decorator); + + Assert.Equal(2, panelNode.Children.Count); + Assert.False(panelNode.Children[0].Disposed); + Assert.False(panelNode.Children[1].Disposed); + } + } + [Fact] public void Should_Update_ClipBounds_For_Negative_Margin() { diff --git a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/VisualNodeTests.cs b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/VisualNodeTests.cs index 24ba2d1c48..3211c3397b 100644 --- a/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/VisualNodeTests.cs +++ b/tests/Avalonia.Visuals.UnitTests/Rendering/SceneGraph/VisualNodeTests.cs @@ -101,5 +101,24 @@ namespace Avalonia.Visuals.UnitTests.Rendering.SceneGraph node.SortChildren(scene); } + + [Fact] + public void TrimChildren_Should_Work_Correctly() + { + var parent = new VisualNode(Mock.Of(), null); + var child1 = new VisualNode(Mock.Of(), null); + var child2 = new VisualNode(Mock.Of(), null); + var child3 = new VisualNode(Mock.Of(), null); + + parent.AddChild(child1); + parent.AddChild(child2); + parent.AddChild(child3); + parent.TrimChildren(2); + + Assert.Equal(2, parent.Children.Count); + Assert.False(child1.Disposed); + Assert.False(child2.Disposed); + Assert.True(child3.Disposed); + } } }