向 NavigationView 添加更多项目需要很长时间
adding more items to NavigationView takes to long
我想向 NavigationView 添加 1500 个项目
我使用了 actionblock 但它仍然很慢并且在 ui
中添加项目需要大约 10 秒
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));
}
}
我想向 NavigationView 添加 1500 个项目 我使用了 actionblock 但它仍然很慢并且在 ui
中添加项目需要大约 10 秒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));
}
}