Browse Source

Merge pull request #10863 from aldelaro5/fix-combobox-issues

InternalSelectionModel: Prevent unwanted source collection changes
pull/11387/head
Steven Kirk 3 years ago
committed by GitHub
parent
commit
c496fb3cec
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 16
      src/Avalonia.Controls/Selection/InternalSelectionModel.cs
  2. 53
      tests/Avalonia.Controls.UnitTests/Primitives/SelectingItemsControlTests.cs

16
src/Avalonia.Controls/Selection/InternalSelectionModel.cs

@ -67,6 +67,8 @@ namespace Avalonia.Controls.Selection
var previousSource = Source;
var previousWritableSelectedItems = _writableSelectedItems;
base.OnSourceCollectionChangeStarted();
try
{
_skipSyncFromSelectedItems = true;
@ -81,8 +83,20 @@ namespace Avalonia.Controls.Selection
// We skipped the sync from WritableSelectedItems before; do it now that both
// the source and WritableSelectedItems are updated.
if (previousSource != Source || previousWritableSelectedItems != _writableSelectedItems)
if (previousWritableSelectedItems != _writableSelectedItems)
{
base.OnSourceCollectionChangeFinished();
SyncFromSelectedItems();
}
else if (previousSource != Source)
{
SyncFromSelectedItems();
base.OnSourceCollectionChangeFinished();
}
else
{
base.OnSourceCollectionChangeFinished();
}
}
private protected override void SetSource(IEnumerable? value)

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

@ -2160,6 +2160,45 @@ namespace Avalonia.Controls.UnitTests.Primitives
}
}
[Fact]
public void Does_Not_Write_To_Bound_SelectedItem_When_DataContext_Changes()
{
// Issue #9438.
var vm1 = new SelectionViewModel();
vm1.Items.Add("foo");
vm1.Items.Add("bar");
vm1.SelectedItem = "bar";
var vm2 = new SelectionViewModel();
vm2.Items.Add("foo");
vm2.Items.Add("bar");
vm2.SelectedItem = "bar";
var target = new SelectingItemsControl
{
DataContext = vm1,
[!ItemsControl.ItemsSourceProperty] = new Binding("Items"),
[!SelectingItemsControl.SelectedItemProperty] = new Binding("SelectedItem"),
Template = Template(),
};
Assert.Equal("bar", target.SelectedItem);
Assert.Equal(1, target.SelectedIndex);
var selectedItemChangedRaised = 0;
vm2.PropertyChanged += (s, e) =>
{
if (e.PropertyName == nameof(vm2.SelectedItem))
{
++selectedItemChangedRaised;
}
};
target.DataContext = vm2;
Assert.Equal(0, selectedItemChangedRaised);
}
private static IDisposable Start()
{
return UnitTestApplication.Start(TestServices.StyledWindow);
@ -2238,6 +2277,7 @@ namespace Avalonia.Controls.UnitTests.Primitives
private class SelectionViewModel : NotifyingBase
{
private int _selectedIndex = -1;
private object _selectedItem;
public SelectionViewModel()
{
@ -2255,6 +2295,16 @@ namespace Avalonia.Controls.UnitTests.Primitives
}
}
public object SelectedItem
{
get => _selectedItem;
set
{
_selectedItem = value;
RaisePropertyChanged();
}
}
public ObservableCollection<string> Items { get; }
public ObservableCollection<string> SelectedItems { get; }
}
@ -2267,6 +2317,9 @@ namespace Avalonia.Controls.UnitTests.Primitives
private class TestSelector : SelectingItemsControl
{
public new static readonly DirectProperty<SelectingItemsControl, IList> SelectedItemsProperty =
SelectingItemsControl.SelectedItemsProperty;
public TestSelector()
{

Loading…
Cancel
Save