2

我正在尝试将相当大的项目列表加载到 WPF DataGrid 中。问题是:它非常缓慢。现在,我的列表中有大约 20,000 个项目,而且需要很长时间(嗯……在我的最新版本中,大约需要 10 秒,但这还不够好)。最近几天我一直在研究它,但我没有找到真正有效的解决方案。

1)当然启用了UI虚拟化(这不再是问题了)

2)我还尝试了 Bea Stollnitz在这里和其他人描述的一些解决方案。这些解决方案很棒,但对我不起作用,因为我的集合必须在运行时更新、过滤和排序,而无需重新加载集合。我找到的解决方案仅适用于 IList 实现......我需要一个 Observable 集合来使我的项目保持最新。

情况就是这样:我确实有我的域数据对象的 Observable 集合(它通过 WCF 异步更新)。我确实有一个 ViewModel 用于包装域对象的列表项。当我打开视图时,我有第二个列表,其中将填充每个域对象的 ViewModel 实例。这是真正的问题。由于“目标”集合绑定到我的 DataGrid,我必须将 ViewModels 的创建分派到 UI 线程(否则 .Net 对来自另一个线程的集合更改不太满意)。所以我用 20,000 个视图模型创建调用污染了 Dispatcher 队列。创建 ViewModel 非常便宜,但调度程序队列中仍有 20,000 个调用,同时 DataGrid 要求同一线程中的 CPU 来填充自己。

我的想法(还没有完成):因为我已经有了 UI 虚拟化,所以我不想在打开视图时创建 ViewModel,而是在运行时需要它们。当用户最初可以看到前 20 个条目时,我只需要创建 20 个 ViewModel 而不是 20,000 个。这是我的问题:我不知道怎么做。那就是你进来的地方:)

我想要这样的东西(不是那样工作..只是为了说明我的意思):

<DataGrid ItemsSource={Binding MyDomainOjectCollection}>
    <DataGrid.RowStyle>
        <Style>
            <Setter Property="DataContext" 
                    Value="{Binding DataContext, 
                            Converter={StaticResource  MyViewModelFactoryConverter}}">
            </Setter>
        </Style>
    </DataGrid.RowStyle>
</DataGrid>

它不一定是转换器,也可以是其他东西或在后面的代码中完成。我不在乎。我需要的是:直接绑定到 DomainObject 集合,动态创建相应的 ViewModel,并使用刚刚创建的 ViewModel 而不是原始对象来填充单行。有任何想法吗?

4

2 回答 2

1

我认为,淹没您的 ObservableCollection 和更新每个项目的 UI 是问题所在。

您应该使用BindingList。您可以在添加一系列项目时禁用其上的事件,如下所示:

BindingList.RaiseListChangedEvents = false;

这将阻止 UI 接收任何事件。然后在批量添加之后,您可以使用以下命令启用它:

BindingList.RaiseListChangedEvents = true;
BindingList.ResetBindings();
于 2011-08-17T21:15:49.383 回答
0

当我打开视图时,我有第二个列表,其中将填充每个域对象的 ViewModel 实例。

很好,那应该是您过滤后的 ObservableCollection。

由于“目标”集合绑定到我的 DataGrid,我必须将 ViewModels 的创建分派到 UI 线程

不,你不知道。ViewModel 是一个非 UI 元素,它可以在任何线程上创建。将这些项目添加到 ObservableCollection 需要在 UI 线程上完成。因此,您可以在任何您喜欢的地方创建所有 VM 包装器,我建议您分批进行,然后将批处理作为一个操作填充到 ObservableCollection 中。现在我知道 ObservableCollection 设置为一次只添加一个项目,但是通过向其添加扩展方法很容易解决这个问题,如前面的 SO answer所示。请注意,您只需在 UI 线程上调用扩展方法,一旦您可以逐个添加项目。

就我个人而言,我会疯狂地争取不一直检索所有数据,我想你已经分析过这个要求并且无法避免它。但是你真的需要在客户端做过滤和排序吗?这不能通过将数据发送到服务器然后用适当的数据回复来实现吗?

无论如何,如果您必须获取所有数据,那么我建议您分批进行(虽然 20K 项目不是一个巨大的数量,但仍然是合理的)。这可以很容易地完成,并且使用视图模型中的属性通知,您可以使过滤后的集合与添加到源集合中的内容保持同步。

于 2011-08-17T21:01:57.193 回答