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(); UpdateContainerSelection();
_selectedItemsSync ??= new SelectedItemsSync(model);
_selectedItemsSync.SelectionModel = model;
if (SelectedIndex != -1) if (SelectedIndex != -1)
{ {
RaiseEvent(new SelectionChangedEventArgs( RaiseEvent(new SelectionChangedEventArgs(

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

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

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

@ -1,5 +1,6 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.Specialized;
using Avalonia.Collections; using Avalonia.Collections;
using Avalonia.Controls.Selection; using Avalonia.Controls.Selection;
using Avalonia.Controls.Utils; using Avalonia.Controls.Utils;
@ -230,6 +231,19 @@ namespace Avalonia.Controls.UnitTests.Utils
Assert.Equal(1, model.SelectedIndex); 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( private static SelectedItemsSync CreateTarget(
IEnumerable<string> items = null) IEnumerable<string> items = null)
{ {
@ -241,5 +255,24 @@ namespace Avalonia.Controls.UnitTests.Utils
var target = new SelectedItemsSync(model); var target = new SelectedItemsSync(model);
return target; 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