From 8ebe1c1288544bbf31426ba7b253b5c79c4acc7b Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 3 Sep 2019 14:49:14 +0200 Subject: [PATCH 1/2] Added failing test for #2901. After the selected item is removed from a `ListBox` with `AlwaysSelected == true`, the container for the newly selected item does not get `:selected` applied. --- .../SelectingItemsControlTests_AutoSelect.cs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_AutoSelect.cs b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_AutoSelect.cs index 72f2b8022f..a7010c521b 100644 --- a/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_AutoSelect.cs +++ b/tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests_AutoSelect.cs @@ -102,6 +102,25 @@ namespace Avalonia.Controls.UnitTests.Primitives Assert.Null(target.SelectedItem); } + [Fact] + public void Removing_Selected_First_Item_Should_Select_Next_Item() + { + var items = new AvaloniaList(new[] { "foo", "bar" }); + var target = new TestSelector + { + Items = items, + Template = Template(), + }; + + target.ApplyTemplate(); + target.Presenter.ApplyTemplate(); + items.RemoveAt(0); + + Assert.Equal(0, target.SelectedIndex); + Assert.Equal("bar", target.SelectedItem); + Assert.Equal(new[] { ":selected" }, target.Presenter.Panel.Children[0].Classes); + } + private FuncControlTemplate Template() { return new FuncControlTemplate((control, scope) => From 5de0bf5fecbc52cb2c8b56323df9b2a7113e568d Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Tue, 3 Sep 2019 14:54:08 +0200 Subject: [PATCH 2/2] Fix AlwaysSelected selected state. Fixes #2901. Two things needed to be done here: - When an item is removed, causing indexes to be reassigned, raise `Recycled` so that `SelectingItemsControl` knows to update the selection state - Update selection state in `SelectingItemsControl` when the selected item changes, but the selected index does not (due to an item being remove) --- src/Avalonia.Controls/Generators/ItemContainerGenerator.cs | 6 ++++++ src/Avalonia.Controls/Primitives/SelectingItemsControl.cs | 5 +++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs index 4fd6f4135c..8d1d69db1c 100644 --- a/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs +++ b/src/Avalonia.Controls/Generators/ItemContainerGenerator.cs @@ -128,6 +128,12 @@ namespace Avalonia.Controls.Generators } Dematerialized?.Invoke(this, new ItemContainerEventArgs(startingIndex, result)); + + if (toMove.Count > 0) + { + var containers = toMove.Select(x => x.Value).ToList(); + Recycled?.Invoke(this, new ItemContainerEventArgs(containers[0].Index, containers)); + } } return result; diff --git a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs index c8c15bc079..44ae89fdbc 100644 --- a/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs +++ b/src/Avalonia.Controls/Primitives/SelectingItemsControl.cs @@ -979,13 +979,14 @@ namespace Avalonia.Controls.Primitives } var item = ElementAt(Items, index); + var itemChanged = !Equals(item, oldItem); var added = -1; HashSet removed = null; _selectedIndex = index; _selectedItem = item; - if (oldIndex != index || _selection.HasMultiple) + if (oldIndex != index || itemChanged || _selection.HasMultiple) { if (clear) { @@ -1022,7 +1023,7 @@ namespace Avalonia.Controls.Primitives index); } - if (!Equals(item, oldItem)) + if (itemChanged) { RaisePropertyChanged( SelectedItemProperty,