diff --git a/src/Avalonia.Controls/SelectionNode.cs b/src/Avalonia.Controls/SelectionNode.cs index 3d560d30c8..562cbdddae 100644 --- a/src/Avalonia.Controls/SelectionNode.cs +++ b/src/Avalonia.Controls/SelectionNode.cs @@ -375,17 +375,29 @@ namespace Avalonia.Controls } } - public void Cleanup() + public bool Cleanup() { - foreach (var child in _childrenNodes) + var result = SelectedCount == 0; + + for (var i = 0; i < _childrenNodes.Count; ++i) { - child?.Cleanup(); + var child = _childrenNodes[i]; - if (child?.SelectedCount == 0) + if (child != null) { - child.Dispose(); + if (child.Cleanup()) + { + child.Dispose(); + _childrenNodes[i] = null; + } + else + { + result = false; + } } } + + return result; } public bool Select(int index, bool select) @@ -729,6 +741,7 @@ namespace Avalonia.Controls { removed.AddRange(_childrenNodes[index]!.SelectedItems); RealizedChildrenNodeCount--; + _childrenNodes[index]!.Dispose(); } _childrenNodes.RemoveAt(index); } diff --git a/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs b/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs index 777bd5496e..fa193466ae 100644 --- a/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs +++ b/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs @@ -931,6 +931,21 @@ namespace Avalonia.Controls.UnitTests }); } + [Fact] + public void Should_Listen_For_Changes_After_Deselect() + { + var target = new SelectionModel(); + var data = CreateNestedData(1, 2, 3); + + target.Source = data; + target.Select(1, 0); + target.Deselect(1, 0); + target.Select(1, 0); + ((AvaloniaList)data[1]).Insert(0, "foo"); + + Assert.Equal(new IndexPath(1, 1), target.SelectedIndex); + } + [Fact] public void Selecting_Item_Raises_SelectionChanged() { @@ -1405,6 +1420,20 @@ namespace Avalonia.Controls.UnitTests } } + [Fact] + public void Removing_Item_Unhooks_CollectionChanged_Handlers() + { + var data = CreateNestedData(2, 2, 2); + var target = new SelectionModel { Source = data }; + + target.SelectAll(); + + var toRemove = (AvaloniaList)data[1]; + data.Remove(toRemove); + + Assert.Equal(0, GetSubscriberCount(toRemove)); + } + [Fact] public void Should_Not_Treat_Strings_As_Nested_Selections() {