From 44cf7f24db15c9f94c33f3ce0bf00d7516f59e55 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 5 Feb 2020 12:44:42 +0100 Subject: [PATCH] Expose API for batch updates. --- src/Avalonia.Controls/SelectionModel.cs | 31 ++++++++++++++----- .../SelectionModelTests.cs | 27 ++++++++++++++++ 2 files changed, 51 insertions(+), 7 deletions(-) diff --git a/src/Avalonia.Controls/SelectionModel.cs b/src/Avalonia.Controls/SelectionModel.cs index c0ae67ff91..bc650907d9 100644 --- a/src/Avalonia.Controls/SelectionModel.cs +++ b/src/Avalonia.Controls/SelectionModel.cs @@ -17,6 +17,7 @@ namespace Avalonia.Controls { private readonly SelectionNode _rootNode; private bool _singleSelect; + private int _operationCount; private IReadOnlyList? _selectedIndicesCached; private IReadOnlyList? _selectedItemsCached; private SelectionModelChildrenRequestedEventArgs? _childrenRequestedEventArgs; @@ -509,6 +510,8 @@ namespace Avalonia.Controls ClearSelection(resetAnchor: true); } + public IDisposable Update() => new Operation(this); + protected void OnPropertyChanged(string propertyName) { RaisePropertyChanged(propertyName); @@ -732,19 +735,33 @@ namespace Avalonia.Controls }); } - private void BeginOperation() => _rootNode.BeginOperation(); + private void BeginOperation() + { + if (_operationCount++ == 0) + { + _rootNode.BeginOperation(); + } + } private void EndOperation() { - var changes = new List(); - _rootNode.EndOperation(changes); + if (_operationCount == 0) + { + throw new AvaloniaInternalException("No selection operation in progress."); + } SelectionModelSelectionChangedEventArgs? e = null; - - if (changes.Count > 0) + + if (--_operationCount == 0) { - var changeSet = new SelectionModelChangeSet(changes); - e = changeSet.CreateEventArgs(); + var changes = new List(); + _rootNode.EndOperation(changes); + + if (changes.Count > 0) + { + var changeSet = new SelectionModelChangeSet(changes); + e = changeSet.CreateEventArgs(); + } } OnSelectionChanged(e); diff --git a/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs b/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs index 1950da2818..c76dc890a9 100644 --- a/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs +++ b/tests/Avalonia.Controls.UnitTests/SelectionModelTests.cs @@ -1466,6 +1466,33 @@ namespace Avalonia.Controls.UnitTests Assert.Equal(1, raised); } + [Fact] + public void Can_Batch_Update() + { + var target = new SelectionModel(); + var raised = 0; + + target.Source = Enumerable.Range(0, 10).ToList(); + target.Select(1); + + target.SelectionChanged += (s, e) => + { + Assert.Equal(new[] { new IndexPath(1) }, e.DeselectedIndices); + Assert.Equal(new object[] { 1 }, e.DeselectedItems); + Assert.Equal(new[] { new IndexPath(4) }, e.SelectedIndices); + Assert.Equal(new object[] { 4 }, e.SelectedItems); + ++raised; + }; + + using (target.Update()) + { + target.Deselect(1); + target.Select(4); + } + + Assert.Equal(1, raised); + } + private int GetSubscriberCount(AvaloniaList list) { return ((INotifyCollectionChangedDebug)list).GetCollectionChangedSubscribers()?.Length ?? 0;