2013-09-22 8 views
2

У меня есть ObservableCollection<T>, который будет содержать много предметов. Данные будут получены асинхронно с использованием фонового рабочего (это работает отлично и быстро).ObservableCollection <T> быстрое заполнение, но медленная визуализация связывания

Но если я попытаюсь связать огромную коллекцию с listbox/listview (независимо) на BackgroundWorkerCompletedTask, визуализация займет много времени, пока графический интерфейс не будет висеть до завершения привязки/визуализации.

Любые идеи о том, как улучшить производительность или предотвратить это поведение?

void bgGetData_DoWork(object sender, DoWorkEventArgs e) 
{ 
    HugeData(); 
} 

void bgGetData_ProgressChanged(object sender, ProgressChangedEventArgs e) 
{ 
    devices.Add((ServiceReference1.Device)e.UserState); 
} 

private void HugeData() 
{ 
    foreach (ServiceReference1.Device dev in Proxy.client.GetHugeDate()) 
    { 
     bgGetData.ReportProgress(0, dev); 
    } 
} 

Данные связаны:

myControl.ItemsSource = devices; 

Спасибо.

+1

если вы использовали ObservableCollection пользовательский интерфейс должен обновлять при каждом обновлении к нему ... Вы можете поделиться код, как у г обновление ObservableCollection? – Nitin

+0

Есть ли способ добавить элементы по частям во время поиска/создания в фоном? Вы могли бы использовать элементы с помощью 'ProgressChanged'. – meilke

+0

попробуйте обновить пользовательский интерфейс с каждым добавленным в коллекцию элементом, а не обновлять всю огромную коллекцию, когда она заканчивается ... –

ответ

0

У меня была очень похожая проблема, как на данные коллекции, так и на настройку GroupNames для элементов в коллекции (я хотел разрешить пустые группы, чтобы вручную обновлять PropertyGroupDescriptor.GroupNames).

Оказывается, что при добавлении к ObservableCollection вы обжиг события CollectionChanged на добавляемого каждый ряда, и если вы изменяете группы вы обновляете группы и строки для каждого группы.

Решение состоит в том, чтобы использовать AddRange в коллекции, которая, к сожалению, не существует, и вы не можете наследовать от ObservableCollection, который содержит имена групп, потому что это происходит из PropertyGroupDescriptor для коллекции, содержащей данные ... но ... cludgiest cludges, которые вы можете получить в базовых Элементах, используя отражение.

Итак, я представляю мой очень неприятный код обновления названия групп: -

public void CheckGroups(ObservableCollection<Object> GroupNames) { 
     var lBindingFlags = BindingFlags.NonPublic | BindingFlags.Instance; 

     if (mHasUpdates) { 

      var lHashC = new HashSet<Object>(GroupNames); 
      var lHashN = new HashSet<Object>(mGroupList); 

      var lAdd = lHashN.Except(lHashC).ToList(); 
      var lRemove = lHashC.Except(lHashN).ToList(); 

      if (lAdd.Count > 0 || lRemove.Count > 0) { 

       var lType = GroupNames.GetType(); 
       var lProp = lType.GetProperty("Items", lBindingFlags); 
       var lItems = (List<Object>)lProp.GetValue(GroupNames, null); 
       var lMethod = lType.GetMethod("OnCollectionChanged", lBindingFlags, null, new Type[] { typeof(NotifyCollectionChangedEventArgs) }, null); 
       var lArgs = new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset); 

       if (lAdd.Count > 0) lItems.AddRange(lAdd); 
       if (lRemove.Count > 0) lItems.RemoveAll(R => lRemove.Contains(R)); 

       lMethod.Invoke(GroupNames, new Object[] { lArgs }); 

      } 
     } 

    } 
Смежные вопросы