From 6072686f9ca89a2ef6cf4d71b6a2132510433e79 Mon Sep 17 00:00:00 2001 From: Edward Miller Date: Fri, 26 Jan 2024 13:24:09 -0600 Subject: [PATCH] Execute notify collection changed events as a batch --- .../ObservableItemTemplateCollection.cs | 47 +++++++++++++++---- .../src/Core/Properties/AssemblyInfo.cs | 2 + 2 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/Controls/src/Core/Platform/Windows/CollectionView/ObservableItemTemplateCollection.cs b/src/Controls/src/Core/Platform/Windows/CollectionView/ObservableItemTemplateCollection.cs index a2866db1dcfd..601811785e7b 100644 --- a/src/Controls/src/Core/Platform/Windows/CollectionView/ObservableItemTemplateCollection.cs +++ b/src/Controls/src/Core/Platform/Windows/CollectionView/ObservableItemTemplateCollection.cs @@ -1,13 +1,14 @@ #nullable disable using System; using System.Collections; -using System.Collections.ObjectModel; +using System.Collections.Generic; using System.Collections.Specialized; -using System.Threading; +using System.Linq; +using Microsoft.Maui.Controls.Internals; namespace Microsoft.Maui.Controls.Platform { - internal class ObservableItemTemplateCollection : ObservableCollection + internal class ObservableItemTemplateCollection : ObservableRangeCollection { readonly IList _itemsSource; readonly DataTemplate _itemTemplate; @@ -164,10 +165,24 @@ void Add(NotifyCollectionChangedEventArgs args) var count = args.NewItems.Count; + List itemsToAdd; + + if (startIndex == 0) + { + itemsToAdd = []; + } + else + { + itemsToAdd = Items.ToList(); + } + for (int n = 0; n < count; n++) { - Insert(startIndex, new ItemTemplateContext(_itemTemplate, args.NewItems[n], _container, _itemHeight, _itemWidth, _itemSpacing, _mauiContext)); + var itemToAdd = new ItemTemplateContext(_itemTemplate, args.NewItems[n], _container, _itemHeight, _itemWidth, _itemSpacing, _mauiContext); + itemsToAdd.Insert(startIndex, itemToAdd); } + + ReplaceRange(itemsToAdd); } void Move(NotifyCollectionChangedEventArgs args) @@ -204,10 +219,15 @@ void Remove(NotifyCollectionChangedEventArgs args) var count = args.OldItems.Count; + List itemsToRemove = []; + for (int n = startIndex + count - 1; n >= startIndex; n--) { - RemoveAt(n); + var itemToRemve = Items[n]; + itemsToRemove.Add(itemToRemve); } + + RemoveRange(itemsToRemove); } void Replace(NotifyCollectionChangedEventArgs args) @@ -216,15 +236,22 @@ void Replace(NotifyCollectionChangedEventArgs args) if (newItemCount == args.OldItems.Count) { + CheckReentrancy(); + + Clear(); + + List newItems = []; + for (int n = 0; n < newItemCount; n++) { - var index = args.OldStartingIndex + n; - var oldItem = this[index]; var newItem = new ItemTemplateContext(_itemTemplate, args.NewItems[n], _container, _itemHeight, _itemWidth, _itemSpacing, _mauiContext); - Items[index] = newItem; - var update = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newItem, oldItem, index); - OnCollectionChanged(update); + newItems.Add(newItem); } + + AddRange(newItems); + + var replace = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Replace, newItems, Items.ToList(), -1); + OnCollectionChanged(replace); } else { diff --git a/src/Controls/src/Core/Properties/AssemblyInfo.cs b/src/Controls/src/Core/Properties/AssemblyInfo.cs index e474d2c631af..b430b01ae921 100644 --- a/src/Controls/src/Core/Properties/AssemblyInfo.cs +++ b/src/Controls/src/Core/Properties/AssemblyInfo.cs @@ -5,6 +5,8 @@ using Compatibility = Microsoft.Maui.Controls.Compatibility; [assembly: InternalsVisibleTo("iOSUnitTests")] +[assembly: InternalsVisibleTo("Microsoft.Maui.Benchmarks.Droid")] +[assembly: InternalsVisibleTo("Microsoft.Maui.Benchmarks.WinUI")] [assembly: InternalsVisibleTo("Microsoft.Maui.Controls.Compatibility.ControlGallery")] [assembly: InternalsVisibleTo("Microsoft.Maui.Controls.Compatibility")] [assembly: InternalsVisibleTo("Microsoft.Maui.Controls.Compatibility.Android")]