diff --git a/src/Avalonia.Controls/SelectionNode.cs b/src/Avalonia.Controls/SelectionNode.cs index ea1a1ca664..e108d0450c 100644 --- a/src/Avalonia.Controls/SelectionNode.cs +++ b/src/Avalonia.Controls/SelectionNode.cs @@ -692,8 +692,17 @@ namespace Avalonia.Controls if (isSelected) { - RemoveRange(new IndexRange(index, index + count - 1), raiseOnSelectionChanged: false); + var removeRange = new IndexRange(index, index + count - 1); + SelectedCount -= IndexRange.Remove(_selected, removeRange); selectionInvalidated = true; + + if (_selectedItems != null) + { + foreach (var i in items) + { + _selectedItems.Remove(i); + } + } } for (int i = 0; i < _selected.Count; i++) diff --git a/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs b/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs index 9ce0816f7d..81b6127eb6 100644 --- a/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs +++ b/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs @@ -1481,7 +1481,7 @@ namespace Avalonia.Controls.UnitTests } [Fact] - public void RetainSelectionOnReset_Retains_Correct_Selection_After_Remove() + public void RetainSelectionOnReset_Retains_Correct_Selection_After_Deselect() { var data = new ResettingList { "foo", "bar", "baz" }; var target = new SelectionModel { Source = data, RetainSelectionOnReset = true }; @@ -1491,7 +1491,35 @@ namespace Avalonia.Controls.UnitTests data.Reset(); Assert.Equal(new[] { new IndexPath(1) }, target.SelectedIndices); - Assert.Equal(new[] { "bar", }, target.SelectedItems); + Assert.Equal(new[] { "bar" }, target.SelectedItems); + } + + [Fact] + public void RetainSelectionOnReset_Retains_Correct_Selection_After_Remove_1() + { + var data = new ResettingList { "foo", "bar", "baz" }; + var target = new SelectionModel { Source = data, RetainSelectionOnReset = true }; + + target.SelectRange(new IndexPath(1), new IndexPath(2)); + data.RemoveAt(2); + data.Reset(new[] { "foo", "bar", "baz" }); + + Assert.Equal(new[] { new IndexPath(1) }, target.SelectedIndices); + Assert.Equal(new[] { "bar" }, target.SelectedItems); + } + + [Fact] + public void RetainSelectionOnReset_Retains_Correct_Selection_After_Remove_2() + { + var data = new ResettingList { "foo", "bar", "baz" }; + var target = new SelectionModel { Source = data, RetainSelectionOnReset = true }; + + target.SelectRange(new IndexPath(1), new IndexPath(2)); + data.RemoveAt(0); + data.Reset(new[] { "foo", "bar", "baz" }); + + Assert.Equal(new[] { new IndexPath(1), new IndexPath(2) }, target.SelectedIndices); + Assert.Equal(new[] { "bar", "baz" }, target.SelectedItems); } [Fact] @@ -1925,6 +1953,15 @@ namespace Avalonia.Controls.UnitTests { public event NotifyCollectionChangedEventHandler CollectionChanged; + public new void RemoveAt(int index) + { + var item = this[index]; + base.RemoveAt(index); + CollectionChanged?.Invoke( + this, + new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Remove, new[] { item }, index)); + } + public void Reset(IEnumerable items = null) { if (items != null)