我有一个以页面形式返回数据的 Rest 服务。我知道得到第一个结果集后有多少页数据。现在我想在 WPF 应用程序中使用此服务,例如在网格控件(或列表视图)中显示结果。
问题是整个分页机制对最终用户应该是透明的,因此他们不应该通过除了在网格中滚动之外的任何方式触发数据获取。这可能吗?您将如何解决这个问题?
我有一个以页面形式返回数据的 Rest 服务。我知道得到第一个结果集后有多少页数据。现在我想在 WPF 应用程序中使用此服务,例如在网格控件(或列表视图)中显示结果。
问题是整个分页机制对最终用户应该是透明的,因此他们不应该通过除了在网格中滚动之外的任何方式触发数据获取。这可能吗?您将如何解决这个问题?
这是您的任务的另一种可能的解决方案:http: //www.devzest.com/blog/post/wpf-data-virtualization.aspx
主要思想是创建自己的IList实现,它将封装所有异步页面加载功能。
作为奖励,该文章包含具有一组附加功能的完整示例代码:
- 选择、排序和过滤效果很好,就像所有数据都存储在本地一样;
- 根据需要在单独的线程中加载数据,不会阻塞 UI;
- 数据加载时的视觉反馈;如果失败,用户可以重试最后一次失败的尝试。
我认为这个问题很有趣,但是对于 stackoverflow 窗口来说答案太长了,所以我构建了一个使用预取集合视图的简单应用程序。
这有点类似于 Woodman 发布的方法。
https://github.com/mrange/CodeStack/tree/master/q14793759/AutoFetching
有趣的代码在类中:PrefetchingCollectionView
将您的网格或列表放入 ScrollViewer,订阅ScrollChanged事件,然后使用事件 args 属性确定您是否足够接近可滚动区域的末尾,并从您的服务请求下一页,最后将接收到的数据添加到末尾列表或网格。
简而言之。如果您需要更具体的示例,请告诉我。
编辑:好的,假设您正在使用System.Windows.Controls.DataGrid
控件来显示您的数据。我做出这个假设是因为您已经说过您的网格确实具有内置的滚动功能,并且没有其他名称类似于网格的控件具有它。也因为使用 DataGrid 进行数据显示是有意义的。:)
您像这样声明您的 DataGrid:
<DataGrid HorizontalAlignment="Left" Margin="20,10,0,0"
VerticalAlignment="Top" Height="301" Width="498"
ScrollViewer.ScrollChanged="DataGrid_ScrollChanged_1"
ItemsSource="{x:Static Fonts.SystemFontFamilies}">
</DataGrid>
请注意,我正在使用ScrollViewer.ScrollChanged
路由事件。这是可能的,因为 DataGrid 确实内置了 ScrollViewer。这意味着可以订阅该事件并分析它的参数。
以下是我出于测试目的处理此事件的方式:
private void DataGrid_ScrollChanged_1(object sender, ScrollChangedEventArgs e)
{
Debug.WriteLine("Extent height: " + e.ExtentHeight +
", vertical offset: " + e.VerticalOffset +
", viewport height: " + e.ViewportHeight);
}
当我的数据网格滚动到顶部时,我看到以下输出:
Extent height: 267, vertical offset: 0, viewport height: 13
当它滚动到底部时:
Extent height: 267, vertical offset: 254, viewport height: 13
因此,很容易确定您何时接近底部并采取相应措施:
const int threshold = 20;
if (e.ExtentHeight <= e.VerticalOffset + e.ViewportHeight + threshold)
{
AskForNextPage();
}
当然,这里有一些细微差别。您需要跟踪您是否已经下载了某些页面,以及您已经加载了多少页面,以避免数据重复和其他不一致。而且,老实说,与我在这里写的相比,这将是最难做的部分。:)