#c# #uwp #navigationview
#c# #uwp #navigationview
Вопрос:
Я хочу добавить 1500 элементов в NavigationView, который я использовал actionblock, но он все еще очень медленный, и для добавления элементов в пользовательский интерфейс требуется около 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 секунду, но добавление элементов в пользовательский интерфейс занимает много времени
Комментарии:
1. У меня уже были подобные проблемы раньше, и это было связано с тем, что пользовательский интерфейс пытался отобразить элементы, даже если они не были видны. Если я помню, мое решение состояло в том, чтобы установить флаг, чтобы не пытаться отображать элементы, которых на самом деле не было на экране. Или мне пришлось использовать другой элемент управления. Точно не помню, но проблема заключалась в том, что пользовательский интерфейс фактически пытался нарисовать все добавляемые элементы, и, похоже, это тоже ваша проблема.
Ответ №1:
Процесс идет медленно , потому ObservableCollection
что реализует INotifyCollectionChanged
интерфейс , в котором вызывается событие CollectionChanged
. Это событие срабатывает каждый раз, когда элемент добавляется в коллекцию, и пользовательский интерфейс (NavigationView) прослушивает его.
Это означает, что каждый раз, когда добавляется элемент, пользовательский интерфейс должен отображать его, что замедляет процесс добавления сотен или тысяч элементов.
Лучше всего реализовать свою собственную версию 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));
}
}