繁体   English   中英

WPF Datagrid 延迟加载

[英]WPF Datagrid Lazy load

细节

  1. VS-2008 专业版 SP1
  2. .net 3.5 版本
  3. 语言:C#

我有一个 WPF Datagrid,它从 Linq-sql 查询 Datacontext 数据项加载。结果集包含大约 200k 行,加载它们、排序、过滤等非常慢。提高速度的简单方法是什么?

我在搜索中看到的几件事是 Scrollview、数据虚拟化等人们也谈论分页、分析等

加载数据: 200k 行是很多数据,没有人(用户)想在一个地方看到。 它肯定会降低您的 UI 用户体验。 所以你最好的办法是过滤你的数据以减少它的数量(例如不显示已关闭的订单,只显示未结订单)。 如果你不能这样做,你应该使用虚拟化。 我没有看到任何使用分页来显示数据的应用程序(当然,网络除外)。 大多数时候这不是一个好方法。 但是,如果您谈论的是一种类似于搜索引擎结果的数据类型,则必须使用它。 但请记住,大多数用户在搜索引擎结果中不会超过第 10 页。

过滤:我建议在您的服务器端为如此大量的数据(此处为 SQL Server)进行过滤,或者正如我所说的,首先过滤整个 200k 以减少服务器端的数量,然后按顺序过滤它(为用户)在客户端找到一些东西。 您可能还会发现以下链接很有帮助:

  1. http://www.codeproject.com/KB/WPF/DataGridFilterLibrary.aspx

排序:我再次建议服务器-客户端解决方案,但您可能还会发现以下链接有用:

  1. http://blogs.msdn.com/b/jgoldb/archive/2008/08/26/improving-microsoft-datagrid-ctp-sorting-performance.aspx
  2. http://blogs.msdn.com/b/jgoldb/archive/2008/08/28/improving-microsoft-datagrid-ctp-sorting-performance-part-2.aspx
  3. http://blogs.msdn.com/b/jgoldb/archive/2008/10/30/improving-microsoft-datagrid-sorting-performance-part-3.aspx

许多人不使用 WPF 数据网格的默认SortMemberPath只是因为它对每条记录使用反射,这将大大降低排序过程的性能。

侯赛因

这是一个非常好的数据虚拟化示例(不是 UI 虚拟化):

http://www.codeproject.com/KB/WPF/WpfDataVirtualization.aspx

尽管它不直接支持 LINQ IQueryable 对象,但您可以按原样使用此示例。 当然,我现在正在努力改进它以直接使用 IQueryable 对象。 我觉得没那么难。

哇,200K 行是很多数据。 分页听起来是个好主意。 试着决定你想要每页多少行,比如 50。第一次显示屏幕时,只显示前 50。然后让用户选择在页面之间移动。

尽管如此,排序可能会更棘手。

虚拟化可能是另一种选择,遗憾的是,我还没有使用虚拟化。

您的数据网格是否在 Scrollviewer 中? 因为它会渲染整个数据网格(所有行)。 我有一个类似的问题,删除滚动查看器解决了加载缓慢的问题。

有时您可能只有大约 30 行可见行要加载,并且如果这些行 + 任何列由于每个单元格的数量和复杂性(它是模板,或者它有多少 wpf 元素)而加载起来很昂贵,那么以上都没有评论真的有所作为。 每一行都需要很长时间才能加载!

有帮助的是交错或延迟加载 UI 上的每一行,以便用户看到 ui 正在执行某些操作,而不仅仅是冻结约 10+ 秒.. 为简单起见,假设数据网格 ItemSource="{Binding Rows} ”,而 Rows 是 IEnumerable,其中 Row 是您创建的某个类:向 Row 添加一个属性 IsVisible(当然不要忘记提高属性已更改)

你可以做这样的事情:

private void OnFirstTimeLoad()
{
    Task.Factory.StartNew(() =>
    {
        foreach (var row in ViewModel.Rows)                                                
        {
            /*this is all you really need, 
              note: since you're on the background thread, make sure IsVisible executes on the UI thread, my utils method does just that*/
              myUtils.ExecuteOnUiThread(() => row.IsVisible = true);

              /*optional tweak: 
              this just forces Ui to refresh so each row repaint staggers nicely*/
              Application.Current.Dispatcher
                         .Invoke(DispatcherPriority.Background, (SendOrPostCallback) delegate { }, null);
         }
       });
}

哦,不要忘记在 XAML 中触发:

<DataGrid.ItemContainerStyle>
    <Style TargetType="{x:Type DataGridRow}">
        <Setter Property="Visibility" Value="{Binding Path=IsVisible, Converter={StaticResource BoolToVisibility}}"/>
      ........

你应该问的问题是:

  1. 用户是否正在浏览 20 万行数据?
  2. 多少数据对用户来说太多了? 可能会提醒用户查询返回的行过多,而您正在列出前 1000 行
  3. 如果用户不查看前 1000 行以外的内容,是否值得您花时间和金钱来编程分页、数据虚拟化等。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM