我想向NavigationView添加1500个项目我使用了actionblock,但它仍然很慢,大约需要10秒才能在ui 中添加项目
private ObservableCollection<NavigationViewItem> data;
TaskScheduler taskScheduler = TaskScheduler.FromCurrentSynchronizationContext();
private void DoSomethingWithCustomer(NavigationViewItem c)
{
Task.Run(() =>
{
data.Add(c);
}).ContinueWith(x =>
{
NavigationView.MenuItemsSource = data;
}, taskScheduler);
}
和:
ActionBlock<NavigationViewItem> action = new ActionBlock<NavigationViewItem>(DoSomethingWithCustomer, new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = Environment.ProcessorCount
});
var coll = System.IO.Directory.EnumerateDirectories("D:\Pic\Art");
foreach (var customer in coll)
{
var item = new NavigationViewItem { Content = new DirectoryInfo(customer).Name };
action.Post(item);
}
action.Complete();
await action.Completion;
我试过了,EnumerateDirectories在不到1秒的时间内完成了。但向ui 添加项目需要很长时间
进程很慢,因为ObservableCollection
实现了INotifyCollectionChanged
接口,该接口有一个名为CollectionChanged
的事件。每当向集合中添加项目并且UI(NavigationView(正在侦听时,就会触发此事件。
这意味着,每次添加项目时,UI都必须对其进行渲染,从而使添加数百或数千个项目的过程变得缓慢。
您最好实现自己版本的ObservableCollection
,它会延迟触发该事件,直到添加所有项目。这里可以找到一个例子:https://peteohanlon.wordpress.com/2008/10/22/bulk-loading-in-observablecollection/
public class RangeObservableCollection<T> : ObservableCollection<T>
{
private bool _suppressNotification = false;
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
if (!_suppressNotification)
base.OnCollectionChanged(e);
}
public void AddRange(IEnumerable<T> list)
{
if (list == null)
throw new ArgumentNullException("list");
_suppressNotification = true;
foreach (T item in list)
{
Add(item);
}
_suppressNotification = false;
OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}