1

We are struggling with the slowness of the datagrid in wpf. Regardless of which collection we are using - List, BindingList, ObservableCollection, custom ObservableCollection, it's still very slow when responding to collection update (Clear, Add) and render on the screen.

The fastest solution we found is not to update the collection, but update the exsting objects in the collection, that DataGrid is bound to. In this case the grid is responding very fast, like old winforms grid.

We are creating 65535 rows in the grid, that will be enough for all our grids. When it comes to update the grid, we update the required number of top rows, and set visibility = hidden for the rest. As I said it works exteremely fast. But There are 2 issues that we cannot solve:

  1. scroll bar, since we don't collapse the rows (it's slow) - it's always is set for 65535 row. Is there any way to limit the scroll, or grid size to the actual visible rows count?

Also, I noticed, that adding new rows into collection, if they don't need to be rendered immediately (they will be out of the visible area) is also very fast, so we can limit the minimum set to 50 rows (max visible rows), and then add/remove new rows as required. But this does not solve the problem with the scrolling.

Any other solutions are welcome. Foreseeing the advise to enable virtualization - yes, we are using virtualization (for rows which are enabled by default, and for columns).

Update: We are trying to display 20 columns x 50 rows of data. If we modify the source collection with Clear() and then Add(), the rendering time is about 1 second, which is not acceptable at all for us, as the UI is frozen for a second. I tried to resize the datagrid to 0 Height, and then set size back incrementally in the background thread, it unfreezes the UI, but overlook is ugly, and I haven't managed how to set datagrid back to fill the parent control. It seems after Height is set in code, there is no way back. As in initial post, the alternate solution we found it not to modify the collection. Just limit the grid to 65535 rows, don't add or remove new items. It works really fast, but now we are facing problems in synchronizing scrolling, and sorting.
I found the datagrid is very frustrating control in WPF. The performance is below any reasonable limits. What we are trying to achieve is responsiveness. It should not block UI more than several milliseconds, when loading the data.

XAML: nothing extraordinary

<DataGrid x:Name="TheGrid" 
                          DockPanel.Dock="Top"
                          ItemsSource="{Binding Collection}"  
                          EnableColumnVirtualization="True"
                          EnableRowVirtualization="True"              
                          AutoGenerateColumns="False"
                          ColumnWidth="70"
                          RowHeight="20"

                          >


                    <DataGrid.Columns>
                        <DataGridTemplateColumn Header="Header 1" >

                            <DataGridTemplateColumn.CellEditingTemplate>
                                <DataTemplate>
                                    <TextBox Text="{Binding Field1, Mode=TwoWay}" />
                                </DataTemplate>
                            </DataGridTemplateColumn.CellEditingTemplate>

                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Field1}" /></DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>

                        </DataGridTemplateColumn >

..... and so on for 20 columns

Also, the datagrid is not inside a StackPanel (this makes it terrible slow).

xll
  • 3,019
  • 2
  • 16
  • 19
  • Are you using `Virtualization` with your Grid? This will only render visible items + a few extras for the scroll buffer, instead of rendering the entire 65535 rows. Perhaps you can post your Grid's XAML and the code for clearing/adding to your `ObservableCollection`? – Rachel Nov 09 '12 at 21:09
  • Yes, I am using the virtualization. When the window maximized, the grid takes about 50 rows x 20 columns, it takes about 1 second to render it, after the collection is updated, or/and the grid becomes visible. – xll Nov 09 '12 at 21:35
  • 1
    You may want to read this awesome article: http://www.codeproject.com/Articles/34405/WPF-Data-Virtualization The described approach won't probably reduce the rendering time, but it will certainly reduce the loading time (I was able to "load" a 20x1000 table in half a second). – skink Nov 09 '12 at 22:28
  • @Joulukuusi Even half a second is too long for us. Using the approach described in the question, the UI is updated in just several milliseconds. WPF is very fast if just need to update the data from bindings. I cannot tell now the exact time - but we load 5000 rows without any loose of UI responsiveness – xll Nov 09 '12 at 22:41

3 Answers3

1

Finally we have found how to limit the scrolling to any number of rows not hacking too much. We created our own list for binding, which implements ICollection, which is used in ScrollView to get count of rows. We changed ICollection.Count to return count of visible rows, which we set before calling Measure, then we set it back to actual count. It works well, and it resolved all our problems with scrolling. So, we have a grid, that is bound to list which has static number of rows, and we set visibility=Visible to n first rows that we want to show, the rest has visibility Hidden (not Collapesed, because Collapsing is very slow), and we limit the scroll to visible rows. The objects that are in list, can be updated from different threads, and we don't need to call Dispatcher, because WPF does it itself.

xll
  • 3,019
  • 2
  • 16
  • 19
0

I have found to pages that might be useful to you.

The first is about caching the values in the datagrid: http://msdn.microsoft.com/en-us/library/system.windows.uielement.cachemode(v=vs.100).aspx

The second it about implementing virtual mode for the datagrid: http://msdn.microsoft.com/en-us/library/15a31akc.aspx

I hope it help you

Update: Are you using a scroll view? Because if you are it will load all rows instead of the visible only. Try see the answer to this question: How to lazy-evaluate a wpf:DataGrid, retrieving data only as needed

Community
  • 1
  • 1
7heViking
  • 7,137
  • 11
  • 50
  • 94
0

I know it might not be the right solution because it still will take the same amount of time. But making it multithreading will solve the freezing problem. Then you could just let it fill data in the grid in the background and add them on the run one by one or add them all when finished.

7heViking
  • 7,137
  • 11
  • 50
  • 94