ObservableCollection <t>快速填充但缓慢的绑定可视化</t>

时间:2013-09-22 10:37:56

标签: c# .net wpf observablecollection

我有一个ObservableCollection<T>,它会包含很多项目。 使用后台工作程序将会异步接收数据(这样可以正常工作)。

但是,如果我尝试将大型集合绑定到BackgroundWorkerCompletedTask的listbox / listview(无论如何),可视化将花费大量时间GUI将挂起,直到绑定/可视化完成。

如何提高性能或防止这种行为?

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 个答案:

答案 0 :(得分:0)

我有一个非常类似的问题,包括集合数据,以及为集合中的项目设置GroupNames(我想允许空组,所以我手动更新PropertyGroupDescriptor.GroupNames)。

事实证明,当添加到ObservableCollection时,您会在添加的每个行上触发CollectionChanged事件,如果您更改了组,则需要更新组和行每个组。

解决方案是在集合上使用AddRange,遗憾的是它不存在,并且您不能从包含组名的ObservableCollection继承,因为它来自集合的PropertyGroupDescriptor保存数据...但是...最常见的cludges你可以使用反射得到基础项目。

所以,我提出了非常令人讨厌的GroupNames更新代码: -

    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 });

            }
        }

    }