简体   繁体   English

WPF Datagrid 延迟加载

[英]WPF Datagrid Lazy load

Details细节

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

I have a WPF Datagrid which loads from Linq-sql query Datacontext data item.The result set contains around 200k rows and its it very slow loading them,sorting,filtering etc. What is the simple and easy way to improve the speed?我有一个 WPF Datagrid,它从 Linq-sql 查询 Datacontext 数据项加载。结果集包含大约 200k 行,加载它们、排序、过滤等非常慢。提高速度的简单方法是什么?

Couple of things I saw searching are Scrollview,Data virtualization etc people also talk about Paging,Profiling etc我在搜索中看到的几件事是 Scrollview、数据虚拟化等人们也谈论分页、分析等

Loading data: 200k rows is a lot of data that no one (user) wants to see in one place.加载数据: 200k 行是很多数据,没有人(用户)想在一个地方看到。 It will definitely reduce your UI user experience.它肯定会降低您的 UI 用户体验。 So your best bet is to filter your data just to reduce the amount of it (for example do not show closed orders, just show the open ones).所以你最好的办法是过滤你的数据以减少它的数量(例如不显示已关闭的订单,只显示未结订单)。 If you can't do so, you should use Virtualization.如果你不能这样做,你应该使用虚拟化。 I didn't see any applications that use pagination in order to show data (Of course except in web).我没有看到任何使用分页来显示数据的应用程序(当然,网络除外)。 Most of the time it isn't such a good approach.大多数时候这不是一个好方法。 But if you are talking about a type of data that is like search engines results you must use it.但是,如果您谈论的是一种类似于搜索引擎结果的数据类型,则必须使用它。 But keep in mind that most users won't exceed page 10 in search engines results.但请记住,大多数用户在搜索引擎结果中不会超过第 10 页。

Filtering: I would suggest doing it on your server side for such a huge amount of data (SQL Server here), or as I said first filter the whole 200k to reduce the amount on server side and then filter it (for user) in order to find something, on the client side.过滤:我建议在您的服务器端为如此大量的数据(此处为 SQL Server)进行过滤,或者正如我所说的,首先过滤整个 200k 以减少服务器端的数量,然后按顺序过滤它(为用户)在客户端找到一些东西。 You might also find the following link helpful:您可能还会发现以下链接很有帮助:

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

Sorting: Again I would suggest server-client solution but you might also find following links helpful:排序:我再次建议服务器-客户端解决方案,但您可能还会发现以下链接有用:

  1. http://blogs.msdn.com/b/jgoldb/archive/2008/08/26/improving-microsoft-datagrid-ctp-sorting-performance.aspx 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 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 http://blogs.msdn.com/b/jgoldb/archive/2008/10/30/improving-microsoft-datagrid-sorting-performance-part-3.aspx

Many people don't use default SortMemberPath of WPF datagrid just because it uses reflection on every single record and this will highly reduce the performance of the sorting process.许多人不使用 WPF 数据网格的默认SortMemberPath只是因为它对每条记录使用反射,这将大大降低排序过程的性能。

Hosein侯赛因

Here is a very good sample of Data Virtualization (Not UI Virtualization):这是一个非常好的数据虚拟化示例(不是 UI 虚拟化):

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

Althogh it doesn't support the LINQ IQueryable objects directly but you can use this sample as it is.尽管它不直接支持 LINQ IQueryable 对象,但您可以按原样使用此示例。 Of course I'm now wokring to improve it to work with IQueryable objects directly.当然,我现在正在努力改进它以直接使用 IQueryable 对象。 I think it's not so hard.我觉得没那么难。

Wow, 200K rows is a lot of data.哇,200K 行是很多数据。 Paging sounds like a good idea.分页听起来是个好主意。 Try to decide how many rows per page you want, say 50. Upon showing the screen the first time, show only the first 50. Then give the user the option to move between pages.试着决定你想要每页多少行,比如 50。第一次显示屏幕时,只显示前 50。然后让用户选择在页面之间移动。

Sorting might be trickier this way though.尽管如此,排序可能会更棘手。

Virtualization can be another option, sadly, I have yet to work with virtualization.虚拟化可能是另一种选择,遗憾的是,我还没有使用虚拟化。

Is your datagrid inside a Scrollviewer?您的数据网格是否在 Scrollviewer 中? Because it does the entire datagrid (all the rows) to be rendered.因为它会渲染整个数据网格(所有行)。 I had a similar problem and removing the scrollviewer solved the problem with the slow loading.我有一个类似的问题,删除滚动查看器解决了加载缓慢的问题。

Sometimes you may have only ~30 visible rows to load and if those rows + whatever columns are expensive to load due to their number and complexity of the each cell (it's template, or how many wpf elements it has), none of the above comments really make a difference.有时您可能只有大约 30 行可见行要加载,并且如果这些行 + 任何列由于每个单元格的数量和复杂性(它是模板,或者它有多少 wpf 元素)而加载起来很昂贵,那么以上都没有评论真的有所作为。 Each row will take it's sweet time to load!每一行都需要很长时间才能加载!

What helps is to stagger or lazily load each row on the UI, so that the user sees that the ui is doing something rather than just freezing for ~10+ seconds.. For simplicity, assuming that the datagrid ItemSource="{Binding Rows}", and Rows is IEnumerable, where Row is some class you created : add a property IsVisible to Row (don't forget to raise property changed, of course)有帮助的是交错或延迟加载 UI 上的每一行,以便用户看到 ui 正在执行某些操作,而不仅仅是冻结约 10+ 秒.. 为简单起见,假设数据网格 ItemSource="{Binding Rows} ”,而 Rows 是 IEnumerable,其中 Row 是您创建的某个类:向 Row 添加一个属性 IsVisible(当然不要忘记提高属性已更改)

you could do something like this:你可以做这样的事情:

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);
         }
       });
}

oh, and don't forget to trigger in XAML:哦,不要忘记在 XAML 中触发:

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

Question that you should be asking is:你应该问的问题是:

  1. Are users groing to look through 200K rows of data?用户是否正在浏览 20 万行数据?
  2. How much data is too much for the users?多少数据对用户来说太多了? May be alert the user that the query returned too many rows and you are listing the first 1000可能会提醒用户查询返回的行过多,而您正在列出前 1000 行
  3. Is it worth your time & money to program paging, Data Virtualization etc if users do not look beyond the first 1000 rows.如果用户不查看前 1000 行以外的内容,是否值得您花时间和金钱来编程分页、数据虚拟化等。

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

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