DataGrid行请求模式与数据虚拟化

时间:2012-09-03 13:14:36

标签: wpf datagrid data-virtualization

我使用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。

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

  • 如果CanSelectMultipleItemsTrue并且用户使用SHIFT按钮或鼠标拖动选择多个项目,则DataGrid会枚举从列表开头到列表的所有行选择结束。无论IEnumerable是否已实施,此枚举均通过IList界面进行。

  • 如果所选行不可见且当前可见区域与所选行“远”,则有时DataGrid会开始请求所有项目,从所选行到可见区域的末尾。包括其间甚至不可见的所有行。我无法弄清楚这种行为的确切模式。也许我的实施就是这个原因。

我的问题

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

  • 为什么有必要要求每一行两到三次?

  • 有人可以告诉我如何使DataGrid不使用IEnumerable,除了关闭多个项目选择吗?

1 个答案:

答案 0 :(得分:5)

我至少找到了一些愚弄VirtualList的方法。你可以阅读它here

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

相关问题