【问题标题】:DataGrid row request patterns with data virtualization具有数据虚拟化的 DataGrid 行请求模式
【发布时间】:2012-09-03 13:14:35
【问题描述】:

我使用CodePlexBea Stollnitz 的博客以及Vincent Da Ven Berhge 的论文(相同链接)中的一些想法实现了一个数据虚拟化解决方案。但是我需要一种不同的方法,所以我决定编写自己的解决方案。

我正在使用DataGrid 来通过此解决方案显示大约一百万行。我也在使用 UI 虚拟化。我的解决方案是可行的,但在某些情况下我会遇到一些奇怪的行为,即DataGrid 如何从其源请求数据。

关于解决方案

我最终写了一个列表来完成所有繁重的工作。它是一个名为VirtualList<T>. 的泛型类,它实现了ICollectionViewFactory 接口,因此集合视图创建机制可以创建一个VirtualListCollectionView<T> 实例来包装它。这个类继承自ListCollectionView。我没有按照建议编写自己的 ICollectionView 实现。继承似乎也可以正常工作。

VirtualList<T> 将整个数据拆分为页面。它获取项目总数,并且每次DataGrid 通过列表索引器请求一行时,它都会加载相应的页面或从缓存中返回它。这些页面在内部被回收,DispatcherTimer 在空闲时间处理未使用的页面。

数据请求模式

  • 我学到的第一件事是,VirtualList<T> 应该实现 IList(非通用)。否则ItemsControl 会将其视为IEnumerable 并查询/枚举所有行。这是合乎逻辑的,因为DataGrid 不是类型安全的,所以它不能使用IList<T> 接口。

  • DataGrid 经常询问索引为 0 的行。它似乎用于视觉项目测量(根据调用堆栈)。所以,我只是把这个缓存起来。

  • DataGrid 内部的缓存机制使用可预测的模式来查询它显示的行。首先它从上到下询问可见行(每行两次),然后在可见区域(包括第一个可见行)之前以降序查询几行(取决于可见区域的大小)顺序如此,从下到上。之后,它从上到下在可见行(包括最后一个可见行)之后请求相同数量的行。

    如果可见行索引是 4,5,6。数据请求将是:4,4,5,5,6,6,4,3,2,1,6,7,8,9。

    如果我的页面大小设置正确,我可以从当前和以前加载的页面处理所有这些请求。

  • 1234563无论是否实现了IList,此枚举都是通过IEnumerable 接口发生的。
  • 如果所选行不可见且当前可见区域与所选行“远”,有时 DataGrid 会开始请求从所选行到可见区域末尾的所有项目。包括其间的所有行,甚至不可见。我无法弄清楚这种行为的确切模式。也许我的实现就是原因。

我的问题

  • 我想知道,为什么DataGrid 请求不可见的行,因为这些行在变得可见时会再次被请求?

  • 为什么要每行请求两三次?

  • 谁能告诉我如何让 DataGrid 不使用IEnumerable,除了关闭多项选择?

【问题讨论】:

    标签: wpf datagrid data-virtualization


    【解决方案1】:

    我至少找到了一些欺骗 VirtualList 的方法。您可以阅读它here

    如果您找到了其他解决方案(甚至比我的更好),请告诉我!

    【讨论】:

    • 是的,我实际上最终做了类似的事情。我返回所有我已经加载的项目,没有别的。从那以后没有引起问题。谢谢
    猜你喜欢
    • 1970-01-01
    • 2016-06-22
    • 2017-11-30
    • 1970-01-01
    • 1970-01-01
    • 2012-04-14
    • 1970-01-01
    • 2014-08-02
    • 2010-12-01
    相关资源
    最近更新 更多