From ee459635a885f4a0094b357b528a459c9ff17b29 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 5 Feb 2020 10:43:12 +0100 Subject: [PATCH] Handle RetainSelectionOnReset w/ null source. --- src/Avalonia.Controls/SelectionNode.cs | 24 +++++++--- .../SelectionModelTests.cs | 45 +++++++++++++++++++ 2 files changed, 62 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Controls/SelectionNode.cs b/src/Avalonia.Controls/SelectionNode.cs index e108d0450c..fea6707b43 100644 --- a/src/Avalonia.Controls/SelectionNode.cs +++ b/src/Avalonia.Controls/SelectionNode.cs @@ -55,11 +55,7 @@ namespace Avalonia.Controls if (_retainSelectionOnReset) { _selectedItems = new List(); - - foreach (var i in SelectedIndices) - { - _selectedItems.Add(ItemsSourceView!.GetAt(i)); - } + PopulateSelectedItemsFromSelectedIndices(); } else { @@ -94,7 +90,7 @@ namespace Avalonia.Controls // Setup ItemsSourceView var newDataSource = value as ItemsSourceView; - + if (value != null && newDataSource == null) { newDataSource = new ItemsSourceView((IEnumerable)value); @@ -102,6 +98,7 @@ namespace Avalonia.Controls ItemsSourceView = newDataSource; + PopulateSelectedItemsFromSelectedIndices(); HookupCollectionChangedHandler(); OnSelectionChanged(); } @@ -453,7 +450,7 @@ namespace Avalonia.Controls { _operation?.Selected(selected); - if (_selectedItems != null) + if (_selectedItems != null && ItemsSourceView != null) { for (var i = addRange.Begin; i <= addRange.End; ++i) { @@ -877,6 +874,19 @@ namespace Avalonia.Controls return selectionState; } + private void PopulateSelectedItemsFromSelectedIndices() + { + if (_selectedItems != null) + { + _selectedItems.Clear(); + + foreach (var i in SelectedIndices) + { + _selectedItems.Add(ItemsSourceView!.GetAt(i)); + } + } + } + private List RecreateSelectionFromSelectedItems() { var removed = new List(); diff --git a/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs b/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs index 81b6127eb6..9574843f99 100644 --- a/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs +++ b/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs @@ -1596,6 +1596,51 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(1, raised); } + [Fact] + public void RetainSelectionOnReset_Handles_Null_Source() + { + var data = new ResettingList { "foo", "bar", "baz" }; + var target = new SelectionModel { RetainSelectionOnReset = true }; + var raised = 0; + + target.SelectionChanged += (s, e) => + { + if (raised == 0) + { + Assert.Empty(e.DeselectedIndices); + Assert.Empty(e.DeselectedItems); + Assert.Equal(new[] { new IndexPath(1) }, e.SelectedIndices); + Assert.Empty(e.SelectedItems); + } + else if (raised == 1) + { + Assert.Empty(e.DeselectedIndices); + Assert.Empty(e.DeselectedItems); + Assert.Equal(new[] { new IndexPath(1) }, e.SelectedIndices); + Assert.Equal(new[] { "bar" }, e.SelectedItems); + } + else if (raised == 3) + { + Assert.Empty(e.DeselectedIndices); + Assert.Empty(e.DeselectedItems); + Assert.Empty(e.SelectedIndices); + Assert.Empty(e.SelectedItems); + } + + ++raised; + }; + + target.Select(1); + Assert.Equal(1, raised); + + target.Source = data; + Assert.Equal(2, raised); + Assert.Equal(new[] { new IndexPath(1) }, target.SelectedIndices); + + data.Reset(new[] { "qux", "foo", "bar", "baz" }); + Assert.Equal(3, raised); + Assert.Equal(new[] { new IndexPath(2) }, target.SelectedIndices); + } private int GetSubscriberCount(AvaloniaList list) {