Browse Source

Restore selection on reset.

pull/4533/head
Steven Kirk 6 years ago
parent
commit
06390d42ee
  1. 3
      src/Avalonia.Controls/Primitives/SelectingItemsControl.cs
  2. 40
      src/Avalonia.Controls/Utils/SelectedItemsSync.cs
  3. 33
      tests/Avalonia.Controls.UnitTests/Utils/SelectedItemsSyncTests.cs

3
src/Avalonia.Controls/Primitives/SelectingItemsControl.cs

@ -798,6 +798,9 @@ namespace Avalonia.Controls.Primitives
UpdateContainerSelection();
_selectedItemsSync ??= new SelectedItemsSync(model);
_selectedItemsSync.SelectionModel = model;
if (SelectedIndex != -1)
{
RaiseEvent(new SelectionChangedEventArgs(

40
src/Avalonia.Controls/Utils/SelectedItemsSync.cs

@ -34,11 +34,14 @@ namespace Avalonia.Controls.Utils
get => _selectionModel;
set
{
value = value ?? throw new ArgumentNullException(nameof(value));
UnsubscribeFromSelectionModel(_selectionModel);
_selectionModel = value;
SubscribeToSelectionModel(_selectionModel);
SyncSelectedItemsWithSelectionModel();
if (_selectionModel != value)
{
value = value ?? throw new ArgumentNullException(nameof(value));
UnsubscribeFromSelectionModel(_selectionModel);
_selectionModel = value;
SubscribeToSelectionModel(_selectionModel);
SyncSelectedItemsWithSelectionModel();
}
}
}
@ -49,16 +52,19 @@ namespace Avalonia.Controls.Utils
{
value ??= new AvaloniaList<object?>();
if (value.IsFixedSize)
if (_selectedItems != value)
{
throw new NotSupportedException(
"Cannot assign fixed size selection to SelectedItems.");
}
if (value.IsFixedSize)
{
throw new NotSupportedException(
"Cannot assign fixed size selection to SelectedItems.");
}
UnsubscribeFromSelectedItems(_selectedItems);
_selectedItems = value;
SubscribeToSelectedItems(_selectedItems);
SyncSelectionModelWithSelectedItems();
UnsubscribeFromSelectedItems(_selectedItems);
_selectedItems = value;
SubscribeToSelectedItems(_selectedItems);
SyncSelectionModelWithSelectedItems();
}
}
}
@ -226,6 +232,12 @@ namespace Avalonia.Controls.Utils
}
}
private void SelectionModelSourceReset(object sender, EventArgs e)
{
SyncSelectionModelWithSelectedItems();
}
private void SubscribeToSelectedItems(IList selectedItems)
{
if (selectedItems is INotifyCollectionChanged incc)
@ -238,6 +250,7 @@ namespace Avalonia.Controls.Utils
{
model.PropertyChanged += SelectionModelPropertyChanged;
model.SelectionChanged += SelectionModelSelectionChanged;
model.SourceReset += SelectionModelSourceReset;
}
private void UnsubscribeFromSelectedItems(IList selectedItems)
@ -252,6 +265,7 @@ namespace Avalonia.Controls.Utils
{
model.PropertyChanged -= SelectionModelPropertyChanged;
model.SelectionChanged -= SelectionModelSelectionChanged;
model.SourceReset -= SelectionModelSourceReset;
}
private static int IndexOf(object? source, object? item)

33
tests/Avalonia.Controls.UnitTests/Utils/SelectedItemsSyncTests.cs

@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using Avalonia.Collections;
using Avalonia.Controls.Selection;
using Avalonia.Controls.Utils;
@ -230,6 +231,19 @@ namespace Avalonia.Controls.UnitTests.Utils
Assert.Equal(1, model.SelectedIndex);
}
[Fact]
public void Restores_Selection_On_Items_Reset()
{
var items = new ResettingCollection(new[] { "foo", "bar", "baz" });
var model = new SelectionModel<string> { Source = items };
var target = new SelectedItemsSync(model);
model.SelectedIndex = 1;
items.Reset(new[] { "baz", "foo", "bar" });
Assert.Equal(2, model.SelectedIndex);
}
private static SelectedItemsSync CreateTarget(
IEnumerable<string> items = null)
{
@ -241,5 +255,24 @@ namespace Avalonia.Controls.UnitTests.Utils
var target = new SelectedItemsSync(model);
return target;
}
private class ResettingCollection : List<string>, INotifyCollectionChanged
{
public ResettingCollection(IEnumerable<string> items)
{
AddRange(items);
}
public void Reset(IEnumerable<string> items)
{
Clear();
AddRange(items);
CollectionChanged?.Invoke(
this,
new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public event NotifyCollectionChangedEventHandler CollectionChanged;
}
}
}

Loading…
Cancel
Save