DataGrid slow to Redraw

13,202

Solution 1

Once there was a little Wolf named MacroSoft, that spend some time with Vidia the Sheep. They made slowest Text and Grid rendering on the planet and pushed all the work onto the CPU in boom year of hardware advance; all while the Sheep made sure to slow it down even further.

If I'm right, you owe a letter to the lot :-)

You are running NVidia card and their crappy drivers or similar as well as seeing MSFT refusing to fix up GDI+ to hardware accelerate along with friendly vendors (even Mono will have it done before they decide to give you some energy saving and proper hardware reuse; you know decent engineering ).

Wrap your DataGridView into a new type (ie. inherit ) and set its DoubleBuffered property to true, change the designer code to use that new type.

Visible "Line by line" rendering is how bad this industry is 2009/2010 with supercomputers on the desktop and single DLL a big company is refusing to fix but will gladly charge for having it execute even slower on Mounta-Dismounta-Vista. Jokers..

Solution 2

Do you have auto-sizing for columns turned on? I've had users experience massive slowdown in our app with as few as 10 rows because auto-sizing was enabled. Basically, one grid allowed a user to check/uncheck a box to add a row to another grid, and the second grid would experience an exponential slowdown with each added row.

After some profiling, I found it was taking ~12 seconds to add 5 rows to the second table. Finally tried turning off the auto-sizing of columns, and it's instantaneous now.

Solution 3

I had big trouble with slow painting datagridview. I needed mine to be as large as possible on the screen, and it seemed the physical size of it had a much greater impact on pain speed than the amount of data, etc. What really did the trick for me was to set CellBorderStyle=None (apparently each cell is responsible for painting its own border, which seems ridiculous since the cell borders remain fixed on the screen so should be no need for every cell to constantly redraw its own borders as you scroll, but anyway...).

Now, a grid without cell borders isn't really a good grid. But fortunately you can set DividerWidth for both columns and rows. Those values are defaulted to 0, but setting them to 1 (or higher if you want thicker) will give you back your "cell" borders identical in appearance to CellBorderStyle=Single, but this time painted "statically" (for lack of better word) for the entire datagridview.

Also, set AutoResize properties to False if you have many rows.

The improvement on paint speed was HUGE, at least in my case.

Solution 4

DataGridView should hanlde 3000 rows with no problems in Virtual Mode.

Make sure to set VirtualMode to true (you mentioned you tried this), and also implement CellValueNeeded properly.

Read the MSDN Walkthrough on VirtualMode for details.

Share:
13,202
Eric Anastas
Author by

Eric Anastas

Updated on October 10, 2022

Comments

  • Eric Anastas
    Eric Anastas over 1 year

    I'm using a System.Windows.Forms.DataGrid. It is populated with about 3000 rows and redraws very slowly. If I minimize and maximize my Form all the other controls just display but I end up watching the DataGrid redraw line by line. Everything in this DataGrid is readonly if that makes a difference.

    Update:

    I'm not really sure how to properly implement the CellValueNeeded() event for my project, or if it would help the performance of the DataGrid in my case.

    I'm creating a User Control that contains a DataGridView (see the code bellow). When the SetProject() method is called my control is set to a specific instance of my Project class. Then the control uses a static method Informa.Data.GetProjectDataTable(Project proj) to extract a DataTable from the Project. The DataSource property of the DataGrid is then set to the returned DataTable.

    This is the first time I've done anything with ADO or DataGrids, so bear with me. It looks like CellValueNeed() allows me to override how a DataGrid finds a value for one of it's cells, but in my case this a lot more complicated then the examples on MSDN. The actual source of my data is a tree structure of various Node objects, the root of which is the Project instance. Each Node can have a variable set of properties, which can also be expanded by the user at runtime. Then there is a bunch of other complexities with Nodes inheriting property values from their parent nodes, and totaling other properties from their child nodes.

    Informa.Data.GetProjectDataTable() cuts through all this craziness and generates a single flat DataTable of all the properties of all the Nodes. At this point I don't care about being able to relate any change of this Table back to the original Tree structure, or updating specific parts of the table when the tree structure changes. All I want to do is display the data to the user in a DataGrid.

    So do I implement CellValueNeeded() to read from the DataTable provided by the Project? I would think a DataGrid would already know how to efficiency use a DataTable as a DataSource?

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Drawing;
    using System.Data;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using Informa;
    
    namespace Informa
    {
    public partial class ProjectGridControl : UserControl
    {
        private Project proj;
    
        public ProjectGridControl()
        {
            InitializeComponent();
        }
    
        public void SetProject(Project proj)
        {
            this.proj = proj;
            UpdateGridControl();
        }
    
        public void UpdateGridControl()
        {
            if (this.proj == null)
            {
                this.dataGrid.DataSource = null;
            }
            else
            {
                //Extracts a DataTable from the project and sets it as the 
                //DataSource of the property grid
                this.dataGrid.DataSource = Informa.Data.GetProjectDataTable(proj);
            }
        }
    }
    

    }

  • Eric Anastas
    Eric Anastas about 15 years
    No auto sizing of both rows and columns is off. Thanks for the suggestion though.
  • Eric Anastas
    Eric Anastas about 15 years
    Yep setting double buffered to true seems to have fixed it. Thanks.
  • Zsolti
    Zsolti almost 13 years
    class DBDataGridView : System.Windows.Forms.DataGridView { public DBDataGridView() { DoubleBuffered = true; } }
  • andzep
    andzep almost 13 years
    @Chris Doggett: THANKS, THANKS, THANKS!!! After 1,5 hrs debugging, found finally your post. And now selecting a row runs about 500% faster ;-)
  • Yisroel M. Olewski
    Yisroel M. Olewski over 12 years
    hi. may i know how to turn off AutoSize? cant find any documentation on it. thanks.
  • VJOY
    VJOY about 12 years
    I am populating Datagridview using bindingsource. I have about 1000 records. I used DoubleBuffered property and set it true. I am still getting it very slow.
  • poy
    poy almost 12 years
    Brilliant observation! Its funny that this makes such a difference.
  • Alex
    Alex over 11 years
    Great observation! I have virtual mode on and nothing helped (I have grid 20x7, 3 updates per 20ms via timer). But this one drastically improved the performance.
  • Dan W
    Dan W over 11 years
    Did you need this solution if you tried the DoubleBuffered solution?