Use single add notify for each element when the new Item is small or the collection hasn't been buffer a lot.

This seems solve the startup stunt and potentially make render faster. (Need Testing)
This commit is contained in:
弘韬 张 2020-11-17 16:46:36 +08:00
parent 23d9e253ba
commit 2b423d9d80

View file

@ -2,6 +2,8 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Configuration;
using System.Linq;
using System.Threading;
using System.Windows;
@ -137,6 +139,7 @@ namespace Flow.Launcher.ViewModel
public void AddResults(List<Result> newRawResults, string resultId)
{
var newResults = NewResults(newRawResults, resultId);
lock (_collectionLock)
{
// https://social.msdn.microsoft.com/Forums/vstudio/en-US/5ff71969-f183-4744-909d-50f7cd414954/binding-a-tabcontrols-selectedindex-not-working?forum=wpf
@ -258,30 +261,38 @@ namespace Flow.Launcher.ViewModel
}
#endregion
public class ResultCollection : ObservableCollection<ResultViewModel>, INotifyCollectionChanged
public class ResultCollection : ObservableCollection<ResultViewModel>
{
private bool _suppressNotification = false;
private long editTime = 0;
// https://peteohanlon.wordpress.com/2008/10/22/bulk-loading-in-observablecollection/
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (!_suppressNotification)
base.OnCollectionChanged(e);
}
public override event NotifyCollectionChangedEventHandler CollectionChanged;
// https://peteohanlon.wordpress.com/2008/10/22/bulk-loading-in-observablecollection/
public void AddRange(IEnumerable<ResultViewModel> Items)
public void BulkAddRange(IEnumerable<ResultViewModel> resultViews)
{
_suppressNotification = true;
foreach (var item in resultViews)
{
Add(item);
}
_suppressNotification = false;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
public void AddRange(IEnumerable<ResultViewModel> Items)
{
foreach (var item in Items)
{
Add(item);
}
// wpf use directx / double buffered already, so just reset all won't cause ui flickering
CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
return;
}
@ -296,16 +307,32 @@ namespace Flow.Launcher.ViewModel
/// <param name="newItems"></param>
public void Update(List<ResultViewModel> newItems, CancellationToken token)
{
Clear();
if (token.IsCancellationRequested)
return;
AddRange(newItems);
Update(newItems);
}
public void Update(List<ResultViewModel> newItems)
{
if (editTime == 0)
{
AddRange(newItems);
editTime++;
return;
}
else if (editTime < 15 || newItems.Count < 50)
{
ClearItems();
AddRange(newItems);
editTime++;
return;
}
Clear();
AddRange(newItems);
BulkAddRange(newItems);
editTime++;
}
}
}