From b80c61892e80df8383efb16eb1ce91d7ca11bd7d Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Sat, 22 Feb 2020 12:49:58 +0100 Subject: [PATCH 1/2] Added failing test for #3551 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Dariusz KomosiƄski --- .../TreeViewTests.cs | 29 +++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs index 32b09e2c47..bd303a81cd 100644 --- a/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs +++ b/tests/Avalonia.Controls.UnitTests/TreeViewTests.cs @@ -1002,6 +1002,35 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(1, child2Node.Presenter.Panel.Children.Count); } + [Fact] + public void Clearing_TreeView_Items_Clears_Index() + { + // Issue #3551 + var tree = CreateTestTreeData(); + var target = new TreeView + { + Template = CreateTreeViewTemplate(), + Items = tree, + }; + + var root = new TestRoot(); + root.Child = target; + + CreateNodeDataTemplate(target); + ApplyTemplates(target); + + var rootNode = tree[0]; + var container = (TreeViewItem)target.ItemContainerGenerator.Index.ContainerFromItem(rootNode); + + Assert.NotNull(container); + + root.Child = null; + + tree.Clear(); + + Assert.Empty(target.ItemContainerGenerator.Index.Containers); + } + private void ApplyTemplates(TreeView tree) { tree.ApplyTemplate(); From 3f3fb1a3f897a803e19998b17f81d1c929afa2e6 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Thu, 9 Apr 2020 10:41:16 +0200 Subject: [PATCH 2/2] Update TreeView index when not attached to logical tree. Fixes #3551. --- src/Avalonia.Controls/TreeViewItem.cs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/Avalonia.Controls/TreeViewItem.cs b/src/Avalonia.Controls/TreeViewItem.cs index a224ceaadd..d3bd45d13c 100644 --- a/src/Avalonia.Controls/TreeViewItem.cs +++ b/src/Avalonia.Controls/TreeViewItem.cs @@ -51,6 +51,7 @@ namespace Avalonia.Controls SelectableMixin.Attach(IsSelectedProperty); FocusableProperty.OverrideDefaultValue(true); ItemsPanelProperty.OverrideDefaultValue(DefaultPanel); + ParentProperty.Changed.AddClassHandler((o, e) => o.OnParentChanged(e)); RequestBringIntoViewEvent.AddClassHandler((x, e) => x.OnRequestBringIntoView(e)); } @@ -179,5 +180,16 @@ namespace Avalonia.Controls return logical != null ? result : @default; } + + private void OnParentChanged(AvaloniaPropertyChangedEventArgs e) + { + if (!((ILogical)this).IsAttachedToLogicalTree && e.NewValue is null) + { + // If we're not attached to the logical tree, then OnDetachedFromLogicalTree isn't going to be + // called when the item is removed. This results in the item not being removed from the index, + // causing #3551. In this case, update the index when Parent is changed to null. + ItemContainerGenerator.UpdateIndex(); + } + } } }