WPF 数据网格性能

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/697701/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 20:13:14  来源:igfitidea点击:

WPF Datagrid Performance

wpfperformancedatagrid

提问by ctrlalt313373

I am working with the WPF Toolkit data grid and it is scrolling extremely slow at the moment. The grid has 84 columns and 805 rows. (Including 3 fixed columns and the header is fixed.) Scrolling both horizontally and vertically is extremely slow. Virtualization is turned on and I have enabled column virtualization and row virtualization explicitly in the xaml. Is there anything to watch out for that can really effect performance, such as binding methods, or what xaml is in each celltemplate?

我正在使用 WPF Toolkit 数据网格,目前它的滚动速度非常慢。网格有 84 列和 805 行。(包括 3 个固定列,标题是固定的。)水平和垂直滚动都非常慢。虚拟化已打开,我已在 xaml 中显式启用列虚拟化和行虚拟化。有什么可以真正影响性能的需要注意的地方,例如绑定方法,或者每个单元格模板中的 xaml 是什么?

One thing to note is I am dynamically adding the columns on creation of the datagrid. Could that be effecting anything? (I also dynamically create the celltemplate at the same time so that my bindings are set right.)

需要注意的一件事是我在创建数据网格时动态添加列。那会不会有什么影响?(我还同时动态创建了 celltemplate,以便我的绑定设置正确。)

Below is the code from the template for most of the cells that get generated. Basically for the columns I need to dynamically add (which is most of them), I loop through my list and add the columns using the AddColumn method, plus I dynamically build the template so that the binding statements properly index the right item in the collection for that column. The template isn't too complex, just two TextBlocks, but I do bind four different properties on each. It seems like I was able to squeeze out a little bit more performance by changes the bindings to OneWay:

以下是大多数生成的单元格的模板代码。基本上,对于我需要动态添加的列(这是大多数),我遍历我的列表并使用 AddColumn 方法添加列,另外我动态构建模板,以便绑定语句正确索引集合中的正确项目对于该列。模板并不太复杂,只有两个 TextBlock,但我确实在每个上绑定了四个不同的属性。似乎我能够通过将绑定更改为 OneWay 来提高一点性能:

 private void AddColumn(string s, int index)
    {
        DataGridTemplateColumn column = new DataGridTemplateColumn();
        column.Header = s;
        //Set template for inner cell's two rectangles
        column.CellTemplate = CreateFactViewModelTemplate(index);
        //Set Style for header, ie rotate 90 degrees
        column.HeaderStyle = (Style)dgMatrix.Resources["HeaderRotateStyle"];
        column.Width = DataGridLength.Auto;
        dgMatrix.Columns.Add(column);
    }


    //this method builds the template for each column in order to properly bind the rectangles to their color
    private static DataTemplate CreateFactViewModelTemplate(int index)
    {
        string xamlTemplateFormat =
            @"<DataTemplate xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation""
            xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"">
            <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition />
                <ColumnDefinition />
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column=""0"" MinHeight=""10"" MinWidth=""10"" HorizontalAlignment=""Stretch"" Padding=""3 1 3 1"" TextAlignment=""Center"" Foreground=""{Binding Path=FactViewModels[~Index~].LeftForeColor,Mode=OneWay}"" Background=""{Binding Path=FactViewModels[~Index~].LeftColor,Mode=OneWay}"" Text=""{Binding Path=FactViewModels[~Index~].LeftScore,Mode=OneWay}"" />
            <TextBlock Grid.Column=""1"" MinHeight=""10"" MinWidth=""10"" HorizontalAlignment=""Stretch"" Padding=""3 1 3 1"" TextAlignment=""Center"" Foreground=""{Binding Path=FactViewModels[~Index~].RightForeColor,Mode=OneWay}"" Background=""{Binding Path=FactViewModels[~Index~].RightColor,Mode=OneWay}"" Text=""{Binding Path=FactViewModels[~Index~].RightScore,Mode=OneWay}"" />
            </Grid>
            </DataTemplate>";




        string xamlTemplate = xamlTemplateFormat.Replace("~Index~", index.ToString());

        return (DataTemplate)XamlReader.Parse(xamlTemplate);
    }

采纳答案by Tobias Hertkorn

Since I can't see your source code it is quite hard to help you. Especially since the performance of a WPF application is influenced by a lot of things. For some hints on what to look out for see Optimizing WPF Application Performance. And yes - it greatly matters what xaml is used in each cell. Because usually performance problems do boil down to "too many elements". Did you know that a TextBox are I think 30 individual elements? I recommend you use the Performance Profiling Tools for WPFto find out more about your specific problem. Try to minimize the amount of elements you are using (e.g. by switching from TextBox to TextBlock where appropriate).

由于我看不到您的源代码,因此很难为您提供帮助。特别是因为 WPF 应用程序的性能受到很多因素的影响。有关注意事项的一些提示,请参阅优化 WPF 应用程序性能。是的 - 在每个单元格中使用什么 xaml 非常重要。因为通常性能问题确实归结为“元素太多”。您知道 TextBox 是 30 个单独的元素吗?我建议您使用WPF 性能分析工具来了解有关您的特定问题的更多信息。尽量减少您使用的元素数量(例如,在适当的情况下从 TextBox 切换到 TextBlock)。

Also you have to check if the performance problems exist on any PC you try the application on. Maybe the PC you are using is forcing WPF into software based rendering. Or are you using any BitmapEffects?

此外,您还必须检查您尝试使用该应用程序的任何 PC 上是否存在性能问题。也许您使用的 PC 正在强制 WPF 进入基于软件的渲染。或者你在使用任何 BitmapEffects 吗?

Edit:
Looking at your code I would suggest you change

编辑:
查看您的代码,我建议您更改

column.Width = DataGridLength.Auto;

column.Width = DataGridLength.Auto;

to a reasonable fixed width, since the datagrid does not have to recalculate the width dynamically every time something changes (like adding rows, or even scrolling).

到合理的固定宽度,因为数据网格不必在每次更改时动态重新计算宽度(例如添加行,甚至滚动)。

回答by TripleAntigen

A general tip for DataGrid performance issues: I had a problem with the DataGrid in which it took literally seconds to refresh after a window resize, column sort, etc. and locked up the window UI while it was doing so (1000 rows, 5 columns).

DataGrid 性能问题的一般提示:我遇到了 DataGrid 的问题,其中在调整窗口大小、列排序等后需要几秒钟才能刷新,并且在执行此操作时锁定了窗口 UI(1000 行,5 列) )。

It came down to an issue (bug?) with the WPF sizing calculations. I had it in a grid with the RowDefinition Height="Auto" which was causing the rendering system to try and recalculate the size of the DataGrid at runtime by measuring the size of each and every column and row, presumably by filling the whole grid (as I understand it). It is supposed to handle this intelligently somehow but in this case it was not.

这归结为 WPF 大小计算的问题(错误?)。我将它放在一个带有 RowDefinition Height="Auto" 的网格中,这导致渲染系统在运行时尝试通过测量每一列和每一行的大小来重新计算 DataGrid 的大小,大概是通过填充整个网格(据我了解)。它应该以某种方式智能地处理这个问题,但在这种情况下它不是。

A quick check to see if this is a related problem is to set the Height and Width properties of the DataGrid to a fixed size for the duration of the test, and try running again. If your performance is restored, a permanent fix may be among these options:

快速检查这是否是相关问题是在测试期间将 DataGrid 的 Height 和 Width 属性设置为固定大小,然后再次尝试运行。如果您的性能恢复,永久修复可能是以下选项之一:

  • Change the sizes of the containing elements to be relative (*) or fixed values
  • Set MaxHeight and MaxWidth of the DataGrid to a fixed value larger than it could get in normal use
  • Try another container type with different resizing strategy (Grid, DockPanel, etc)
  • 将包含元素的大小更改为相对 (*) 或固定值
  • 将 DataGrid 的 MaxHeight 和 MaxWidth 设置为比正常使用时更大的固定值
  • 尝试使用不同大小调整策略的另一种容器类型(Grid、DockPanel 等)

回答by Hans van Dodewaard

in one of my projects the following grid style setting was causing a major performance problem:

在我的一个项目中,以下网格样式设置导致了一个主要的性能问题:

 <Style  TargetType='{x:Type controls:DataGrid}'>
    <Setter Property='ScrollViewer.CanContentScroll' Value='False' />
    ...

When I removed the ScrollViewer.CanContentScroll setting, the performance problem was gone.

当我删除 ScrollViewer.CanContentScroll 设置时,性能问题就消失了。

回答by Ingo Eichenseher

I had a case where my underlying object had property with setter only. The same property was accessible by implementing ITypedList in the collection and via TypeDescriptionProvider/ICustomTypeDescriptor on the individual objects. Either removing the property or adding a getter resolved the performance issues.

我有一个案例,我的底层对象只有 setter 的属性。通过在集合中实现 ITypedList 并通过各个对象上的 TypeDescriptionProvider/ICustomTypeDescriptor 可以访问相同的属性。删除属性或添加 getter 都解决了性能问题。

回答by Vibes

One thing that I would suggest in such scenarios is to look at how you have applied the styling and what the style is on each cell. The styling applied if it has a complex Visual Tree does tend to degrade performance.

在这种情况下,我建议的一件事是查看您如何应用样式以及每个单元格上的样式是什么。如果它具有复杂的可视化树,则应用的样式确实会降低性能。

You could also try the Deferred Scrolling option on the latest WPF Datagrid.

您还可以在最新的 WPF Datagrid 上尝试延迟滚动选项。

回答by Jon Kragh

Do you by any chance have a tablet of any sort installed (via USB or a tablet PC)?

您是否有安装过任何类型的平板电脑(通过 USB 或平板电脑)?

I found a performance bug in the WPF datagrid when using a tablet. I posted a video and it is acknowledged by MS here in this thread

我在使用平板电脑时在 WPF 数据网格中发现了一个性能错误。我发布了一个视频,并在此线程中得到了 MS 的认可

Cheers, Jon

干杯,乔恩