Browse Source

Fix AlwaysSelected in conjuction with SelectedItem/SelectedIndex binding (#14107)

* Added failing tests for #12733.

* Clear SkipLostSelection on batch update start.

If `Source` is changed during a collection update, then the `Clear()` operation will not be committed immediately due to `_isSourceCollectionChanging` being set. In this case, `update.Operation` will still have `SkipLostSelection == true`, meaning that `LostSelection` will not be raised, causing #12733. Clear the flag manually each time `BeginBatchUpdate` is called to avoid this.

Fixes #12733

---------

Co-authored-by: Max Katz <maxkatz6@outlook.com>
pull/14533/head
Steven Kirk 2 years ago
committed by GitHub
parent
commit
3692960ce5
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 1
      src/Avalonia.Controls/Selection/SelectionModel.cs
  2. 19
      tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs
  3. 33
      tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Single.cs

1
src/Avalonia.Controls/Selection/SelectionModel.cs

@ -203,6 +203,7 @@ namespace Avalonia.Controls.Selection
public void BeginBatchUpdate() public void BeginBatchUpdate()
{ {
_operation ??= new Operation(this); _operation ??= new Operation(this);
_operation.SkipLostSelection = false;
++_operation.UpdateCount; ++_operation.UpdateCount;
} }

19
tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs

@ -2292,6 +2292,25 @@ namespace Avalonia.Controls.UnitTests.Primitives
} }
[Fact]
public void Changing_DataContext_Respects_AlwaysSelected()
{
// Issue #12733
var target = new ListBox
{
DataContext = Enumerable.Range(0, 10).ToList(),
SelectionMode = SelectionMode.AlwaysSelected,
Template = Template(),
[!ListBox.ItemsSourceProperty] = new Binding(),
};
Assert.Equal(0, target.SelectedIndex);
target.DataContext = Enumerable.Range(10, 10).ToList();
Assert.Equal(0, target.SelectedIndex);
}
[Theory] [Theory]
[MemberData(nameof(GetSelectionFieldPermutationParameters))] [MemberData(nameof(GetSelectionFieldPermutationParameters))]
public void SelectedItem_And_Selection_Properties_Work_In_Any_Order_When_Initializing(SelectionField[] fields) public void SelectedItem_And_Selection_Properties_Work_In_Any_Order_When_Initializing(SelectionField[] fields)

33
tests/Avalonia.Controls.UnitTests/Selection/SelectionModelTests_Single.cs

@ -1,4 +1,5 @@
using System; using System;
using System.Collections;
using System.Collections.Specialized; using System.Collections.Specialized;
using System.Linq; using System.Linq;
using Avalonia.Collections; using Avalonia.Collections;
@ -1346,6 +1347,38 @@ namespace Avalonia.Controls.UnitTests.Selection
Assert.Equal(0, raised); Assert.Equal(0, raised);
} }
[Fact]
public void LostSelection_Is_Called_When_Source_Changed_While_CollectionChange_In_Progress()
{
// Issue #12733.
var data1 = new AvaloniaList<string> { "foo1", "bar1", "baz1" };
var data2 = new AvaloniaList<string> { "foo1", "bar1", "baz1" };
var target = new DerivedSelectionModel { Source = data1 };
var raised = 0;
target.LostSelection += (s, e) =>
{
if (target.Source == data2)
{
++raised;
}
};
target.UpdateSource(data2);
Assert.Equal(1, raised);
}
private class DerivedSelectionModel : SelectionModel<string?>
{
public void UpdateSource(IEnumerable? source)
{
OnSourceCollectionChangeStarted();
Source = source;
OnSourceCollectionChangeFinished();
}
}
} }
public class UntypedInterface public class UntypedInterface

Loading…
Cancel
Save