46

I have tried using both a customized DataGrid as well as the stock one in WPF. I have tried populating them manually as well as through bindings. In both cases they are slow.

I have a scenerio where the user clicks on a button and a DataGrid appears with appropriate data. Currently I am in proof of concept mode and just using sample data. I have a DataSet with a table that has 10 rows in it.

If I don't attach any data to the DataGrid when I click the button the empty DataGrid displays pretty much instantly, a user cannot perceive a delay. As soon as I add 10 rows of data, for 6 columns, the delay is about 2 seconds, very noticable to the user.

I even tried filling with empty data, just to get an empty grid to appear and it is equally as slow.

for (int i = 0; i < 10; i++)
    _dataGrid.Items.Add("");

I put a timer to count the ticks from when the button is clicked to when all of the code is executed to draw the DataGrid and it is around 20 milliseconds, so the code executes very fast, but on the screen is where the big lag is. I tried a GridView and it renders much fast on the screen.

I have heard various reports of slow DataGrid drawing with complex scenarios and using 1000's of rows, but this is as simple as it gets, 6 columns by 10 rows filled with empty data.

For readonly display is GridView an equally viable option to the DataGrid?


Update

Here is the creation of my columns.

                DataGridTextColumn column = new DataGridTextColumn();
                column.ColumnWidthChanged += new ColumnWidthChangedEventHandler(column_ColumnWidthChanged);

                column.Header = entity.GetPropertyValue("ColumnLabel");
                column.Binding = new Binding(entity.GetPropertyValue("Tag"));
                column.Width = new DataGridLength(entity.GetPropertyDouble("DisplaySize"));
                _dataGrid.Columns.Add(column);

This is a how I bind the DataSet with 10 rows in it.

                _dataGrid.ItemsSource = ds.Tables[0].DefaultView;
                _dataGrid.DataContext = ds.Tables[0];

Not sure what I can do differently.

David Gunther
  • 461
  • 1
  • 5
  • 5
  • I have tried the app on another system as well and it was slow as well. The problem is that some view have multiple DataGrid's on them, so the delay just increases for each additional DataGrid. – David Gunther Jul 13 '11 at 15:23
  • i use the standard wpf datagrid with dynamic columns and more then 10000rows and have no problem with that. whats your itemssource? a datatable or somekind of collection? hopefully you did not add the items in a foreach like you post?? – blindmeis Jul 13 '11 at 15:57
  • I tried the for loop as in the post just to see if it would make a difference, I wasn't sure if the binding was the problem. In the real case I have a DataSet that I am binding. I will update the post. – David Gunther Jul 13 '11 at 19:39
  • 1
    Very closely related: http://stackoverflow.com/questions/697701/wpf-datagrid-performance/7413000#7413000 – Robert Harvey Dec 28 '11 at 04:32
  • I am currently having the same issue, the code is executing pretty quickly, but the UI is updated in 6 minutes (my DataGrid has more than 60k items). None of the other comments seemed to help, did you manage to fix it somehow? – Raya Sep 29 '21 at 14:58

11 Answers11

41

Are you have:

  • Enabled VirtualizingStackPanel.VirtualizationMode for a Grid? if not - try to set.
  • Set VirtualizingStackPanel.IsVirtualizing="true" for DataGrid
  • Wrapped up a Grid by a StackPanel container? If yes - try to remove.
  • Wrapped up a Grid by an external ScrollViewer control? If yes - try to remove.

One more point, could you bind whole items collection at once instead of adding each item into the grid.Items collection?

sll
  • 61,540
  • 22
  • 104
  • 156
  • Tried pasting my XAML but didn't come out well, I'll try and update my original question. The DataGrid is contained within a DockPanel. No to the ScrollViewer and I do not reference VirtualizingStackPanel.VirtualizationMode. – David Gunther Jul 13 '11 at 15:16
  • Try to set VirtualizingStackPanel.VirtualizationMode to Recycling, for instance: – sll Jul 13 '11 at 15:39
  • Thank for the suggestion, but it doesn't appear to have helped. – David Gunther Jul 13 '11 at 16:43
  • Surely you tried to add this property to DataGrid control not a Grid? Also try to set VirtualizingStackPanel.IsVirtualizing="true" for DataGrid – sll Jul 14 '11 at 08:18
  • Yes, I had tried it on a DataGrid, added IsVirtualizing as well and it actually seemed to slow it down. I am really perplexed. The code executes very fast, it is just the update that is slow. – David Gunther Jul 14 '11 at 11:42
  • 3
    Thanks man for the post, I didn`t think that inserting datagrid in stack panel can result in a rendering speed so much. In my case the difference in stack panel and outside was nearly 100 times. – Vahagn Nahapetyan Mar 18 '16 at 19:17
  • Nothing of this works. DataGrid in WPF is far worse than the WinForms grid regarding performance, it's almost unusable. – Hrvoje Batrnek Oct 16 '20 at 02:09
  • @HrvojeBatrnek nothing of this worked for me as well, did you find any solution? – Raya Sep 30 '21 at 09:27
  • 1
    @RayaChorbadzhiyska yes. The problem is shadows effects, turn them off in the grid cells, in the grid containers, turn off all effects in the entire hierarchy and see what happens. My grid container had shadow effects. Shadow effects are very inefficient. That solved my problem. – Hrvoje Batrnek Sep 30 '21 at 13:06
33

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).

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.

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:

  • 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)
Robert Harvey
  • 178,213
  • 47
  • 333
  • 501
TripleAntigen
  • 2,221
  • 1
  • 31
  • 44
  • 5
    I had the same problem with a DataGrid contained in a layout Grid's star-sized row. Setting MaxHeight as suggested works like a charm. – EagleBeak Mar 11 '14 at 15:09
19

A blog I found on Google gave me a sort-of solution. As the author said, I disabled GroupStyle, and the rendering speed issue was solved. But I needed grouping. The author said

VirtualizingPanel.IsVirtualizingWhenGrouping

is added to .NET 4.5. So I set it to true. Now rendering is quick with grouping. The problem is... scrolling is jerky. Not unacceptably jerky, but noticeably jerky. I had similar problem when I tried to create a TreeView with 2000+ nodes expanded. Without virtualisation, rendering was slow but scrolling was smooth. With virtualisation, rendering was quick but scrolling was jerky.

Why can't we have both...

Damn Vegetables
  • 11,484
  • 13
  • 80
  • 135
  • 1
    This single line solved my exact problem - thank you very much! I was messing around with the asyn Task I'm using for loading the data when I finally realized that the rendering was the real problem. Added `VirtualizingPanel.IsVirtualizingWhenGrouping="True"` and the population of my DataGrid ist now down from around 10 seconds to less than a second. – M463 Jun 09 '16 at 16:18
  • This one also worked for me! Went down from 10-30 seconds to less than 1. – Will Wainwright Oct 28 '16 at 03:30
  • What is the solution when not using grouping? – AndrewRalon Jul 19 '19 at 16:10
  • This was the solution for me too. But "Why can't we have both..."? is a really good question. – h.m.i.13 Jul 21 '23 at 16:15
12

In my case I had a problem with DataGridCell ControlTemplate that slowed rendering way down.

Be aware that relative loading speeds for large dataset are very different for using TextBlock (that is not selectable text) or TextBox in ReadOnly mode:

Loading time 59 seconds:

<Style TargetType="{x:Type DataGridCell}" x:Key="DataGridCellTextStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                    <TextBox IsReadOnly="True" Text="{Binding Mode=OneWay}"/> 
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Loading time 21 seconds:

<Style TargetType="{x:Type DataGridCell}" x:Key="DataGridCellTextStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                     <ContentPresenter Content="{Binding}" />
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

Loading time 16 seconds:

<Style TargetType="{x:Type DataGridCell}" x:Key="DataGridCellTextStyle">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type DataGridCell}">
                    <TextBlock Text="{Binding}"></TextBlock>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
Evalds Urtans
  • 6,436
  • 1
  • 41
  • 31
7

Well a little bit adding more (i know its very old topic, but still it helps someone)...

I tried

EnableColumnVirtualization="True" VirtualizingPanel.VirtualizationMode="Recycling"
EnableRowVirtualization="True" 

for DataGrid(AutoGenerateColumns="True") binding to DataTable.DefaultView() and No effect on speed, it was still horrible for Speed as well as for navigation between rows. Than, I came up with solution to set Fixed Height and Width of DataGrid. Additionally I also set

RowHeight="23" 
ScrollViewer.HorizontalScrollBarVisibility="Visible"
ScrollViewer.VerticalScrollBarVisibility="Visible"

This makes my page fill very fast... Instead of 2 min, now it takes hardly 10-12 seconds.

Hope it helps someone.

Note: I am using .Net 4.5

Nirav Raval
  • 117
  • 1
  • 6
5

For me it was:

<Setter Property='ScrollViewer.CanContentScroll' Value='False' />

I removed this from the style and the rendering became fast.

waxingsatirical
  • 584
  • 1
  • 7
  • 11
  • 1
    To clarify, set ScrollViewer.CanContentScroll to `true` as a value of `false` will disable virtualization. – Slate Dec 04 '17 at 17:49
  • With CanContentScroll on false I had 20s load time... on true, load time is instant. But the smooth scrolling is gone. – Welcor Aug 09 '19 at 17:45
5

I was having big issues with 1000 rows, 5 columns where the render time was taking 7-10 seconds, but the solution found at https://www.elegant-software.net/2014/05/performance-of-the-wpf-datagrid.html made the grid load instantly!

<DataGrid
   EnableRowVirtualization="True"
   EnableColumnVirtualization="True">
Nick
  • 461
  • 5
  • 17
  • 2
    As a quick update on this - In my scenario, I had a checkbox at the end of each row for users to select which rows they needed and once complete, they would submit the selected, but I found when row virtualisation was enabled, due to its nature of only rendering what's on screen, it didn't count the selected rows that were not visible on screen which led to a couple of issues. To combat this, I added/removed the selected IDs to a hashset variable whenever the row was selected, and tracked them this way – Nick Mar 18 '19 at 12:58
2

I have a Surface Pro 3 on which my datagrid, with about 200 rows and 10 columns, was really slow at scrolling, jerky and hesitant.

I thought it was the network, but it was in fact the graphics card not being able to keep up with - wait for it - a drop shadow effect on the datagrid itself, even though the background of the control was set to a solid colour.

I commented out the effect and it was 4-5 times faster.

Hope this helps.

0

I have same problem with bound Data grid, and I notice that in first load it is fast but on secand and next it is slow. So when I add in code

DataGrid.ItemsSource = Nothing and then TableAdapter.Fill(Mydataset.MyStoredProcedure,....) DataGrid.ItemsSource=Mydataset.MyStoredProcedure it became very FAST

HaveNoDisplayName
  • 8,291
  • 106
  • 37
  • 47
SLAVICA
  • 9
  • 1
0

My problem was that I had ScrollViewer.CanContentScroll="False" set on my DataGrid. This disables virtualization all together for the DataGrid. More info about this can be found here:

https://stackoverflow.com/a/3724695/4383302

0

If you have row definition like belove:

 <Grid.RowDefinitions>
        <RowDefinition x:Name="topRow" Height="*"/>
        <RowDefinition x:Name="mainRow" Height="*"/>
        <RowDefinition x:Name="dataGridRow" Height="*"/>
    </Grid.RowDefinitions>

You must be carefull! Such as if your Datagrid in one of these rows then it will be resized for every row over and over again. If you have 1000 rows then it will be resized 1000 times your Datagrid!

Let us tell that your Datagrid is in 3rd RowDefinition then what I suggest is you to change the code on this way.

     <Grid.RowDefinitions>
        <RowDefinition x:Name="topRow" Height="*"/>
        <RowDefinition x:Name="mainRow" Height="*"/>
        <RowDefinition x:Name="dataGridRow" Height="400"/>
    </Grid.RowDefinitions>

Of course you can also change "400" how you wish.