Browse Source

Hackfix for calling SelectAll with SelectedItem binding (#13868)

* Added failing tests for #13676.

* Add hackfix for #13676.

---------

Co-authored-by: Max Katz <maxkatz6@outlook.com>
pull/13893/head
Steven Kirk 2 years ago
committed by GitHub
parent
commit
0a6987b085
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 14
      src/Avalonia.Controls/Selection/SelectionModel.cs
  2. 59
      tests/Avalonia.Controls.UnitTests/ListBoxTests_Multiple.cs

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

@ -69,6 +69,18 @@ namespace Avalonia.Controls.Selection
get => _selectedIndex;
set
{
if (_operation is not null && _operation.UpdateCount == 0)
{
// An operation is in the process of being committed. In this case, if the new
// value for SelectedIndex is unchanged then we need to ignore it. It could be
// the result of a two-way binding to SelectedIndex writing back to the
// property. The binding system should really be fixed to ensure that it's not
// writing back the same value, but this is a workaround until the binding
// refactor is complete. See #13676.
if (value == _selectedIndex)
return;
}
using var update = BatchUpdate();
Clear();
Select(value);
@ -675,8 +687,6 @@ namespace Avalonia.Controls.Selection
}
}
if (raisePropertyChanged)
{
if (oldSelectedIndex != _selectedIndex)

59
tests/Avalonia.Controls.UnitTests/ListBoxTests_Multiple.cs

@ -3,6 +3,7 @@ using System.Linq;
using Avalonia.Controls.Presenters;
using Avalonia.Controls.Primitives;
using Avalonia.Controls.Templates;
using Avalonia.Data;
using Avalonia.Input;
using Avalonia.Input.Platform;
using Avalonia.Styling;
@ -577,6 +578,64 @@ namespace Avalonia.Controls.UnitTests
Assert.True(target.ContainerFromIndex(3).IsFocused);
}
[Fact]
public void SelectAll_Works_From_No_Selection_When_SelectedItem_Is_Bound_TwoWay()
{
// Issue #13676
using var app = UnitTestApplication.Start(TestServices.RealFocus);
var target = new ListBox
{
Template = new FuncControlTemplate(CreateListBoxTemplate),
ItemsSource = new[] { "Foo", "Bar", "Baz", "Qux" },
SelectionMode = SelectionMode.Multiple,
Width = 100,
Height = 100,
};
var root = new TestRoot(target);
root.LayoutManager.ExecuteInitialLayoutPass();
target.Bind(ListBox.SelectedItemProperty, new Binding("Tag")
{
Mode = BindingMode.TwoWay,
RelativeSource = new RelativeSource(RelativeSourceMode.Self),
});
target.SelectAll();
Assert.Equal(new[] { 0, 1, 2, 3 }, target.Selection.SelectedIndexes);
Assert.Equal(new[] { "Foo", "Bar", "Baz", "Qux" }, target.SelectedItems);
}
[Fact]
public void SelectAll_Works_From_No_Selection_When_SelectedIndex_Is_Bound_TwoWay()
{
// Issue #13676
using var app = UnitTestApplication.Start(TestServices.RealFocus);
var target = new ListBox
{
Template = new FuncControlTemplate(CreateListBoxTemplate),
ItemsSource = new[] { "Foo", "Bar", "Baz", "Qux" },
SelectionMode = SelectionMode.Multiple,
Width = 100,
Height = 100,
};
var root = new TestRoot(target);
root.LayoutManager.ExecuteInitialLayoutPass();
target.Bind(ListBox.SelectedIndexProperty, new Binding("Tag")
{
Mode = BindingMode.TwoWay,
RelativeSource = new RelativeSource(RelativeSourceMode.Self),
});
target.SelectAll();
Assert.Equal(new[] { 0, 1, 2, 3 }, target.Selection.SelectedIndexes);
Assert.Equal(new[] { "Foo", "Bar", "Baz", "Qux" }, target.SelectedItems);
}
private Control CreateListBoxTemplate(TemplatedControl parent, INameScope scope)
{
return new ScrollViewer

Loading…
Cancel
Save