locked
datagridview slow to draw RRS feed

  • Question

  • I have an application where its a form with a tabcontrol.

    i'll have about 14 tabpages and a datagridview on each tab.  When the applaction is first opened up, the datagradview with lots of data takes up to 10 seconds to draw itself out. 

    How can I figure out what is causing this?  Seems like with the data already there in the grid, it should not take as long.

    Sunday, February 16, 2014 7:30 AM

Answers

  • Hi,

    >> But if anyone one else has some idea on how to load a few hundred records at a time into a data grid view and keep track of what’s loaded there, and how to fetch the next or previous 100 rows.<<

    In my view, we can use stored procedures and paging to achieve this goal. I created a general sample to achieve this goal,

    Stored procedure:

    CREATE PROCEDURE dbo.pagination 
     (
     @PageSize int = 10,
     @CurrentPageIndex int=1 
     )
     
    AS
       declare @index int
     if(@CurrentPageIndex=1)
       begin
          EXEC( 'SELECT TOP ' + @PageSize +  '* from Orders ')
       end
     else
       begin
       set @index= (@CurrentPageIndex-1) * @PageSize
            EXEC( 'SELECT TOP ' + @PageSize +  '* from Orders where OrderId not in '
            +'(select top '+ @index +'OrderId from Orders ) ')
          end
     RETURN

    VB.NET Code:

    Private Const pageSize As Integer = 10
    
    Private dtInfo As DataTable = Nothing
    Protected Function ConnectStr() As String
    
    	Dim _connnectionStr As String = [String].Format("Data Source=localhost;AttachDbFilename={0};Integrated Security=True", "F:\xyt\MyProject\DataGridView\DataGridViewAndCheckBox\DataGridViewAndCheckBox\bin\Debug\b2bdb_Data.MDF")
    	'connection string
    	Return _connnectionStr
    End Function
    
    Private Function LoadData(PageIndex As Integer) As DataTable
    	Dim con As New SqlConnection(Me.ConnectStr())
    	Dim cmd As New SqlCommand("pagination", con)
    	cmd.CommandType = CommandType.StoredProcedure
    	con.Open()
    	cmd.Parameters.Add(New SqlParameter("@PageSize", SqlDbType.Int, 4))
    	cmd.Parameters("@PageSize").Value = pageSize
    	cmd.Parameters.Add(New SqlParameter("@CurrentPageIndex", SqlDbType.Int, 4))
    	cmd.Parameters("@CurrentPageIndex").Value = PageIndex
    
    	Dim dt As New DataTable()
    	Dim adapter As New SqlDataAdapter(cmd)
    	adapter.Fill(dt)
    
    	con.Close()
    	Return dt
    
    End Function
    
    Private Sub Form1_Load(sender As Object, e As EventArgs)
    	dtInfo = LoadData(1)
    	Me.dataGridView1.DataSource = dtInfo
    	Me.label1.Text = Convert.ToString(1)
    
    End Sub
    
    Private Sub btnNext_Click(sender As Object, e As EventArgs)
    	Me.label1.Text = (Convert.ToInt32(Me.label1.Text) + 1).ToString()
    	dtInfo = LoadData(Convert.ToInt32(Me.label1.Text))
    	If dtInfo.Rows.Count = 0 Then
    		'This is the last page.
    		Me.label1.Text = (Convert.ToInt32(Me.label1.Text) - 1).ToString()
    		MessageBox.Show("This is the last page.")
    	Else
    		Me.dataGridView1.DataSource = Nothing
    		Me.dataGridView1.DataSource = dtInfo
    	End If
    End Sub
    
    Private Sub btnPrevious_Click(sender As Object, e As EventArgs)
    
    	If Me.label1.Text = "1" Then
    		MessageBox.Show("This is first page")
    		Return
    	Else
    		Me.label1.Text = (Convert.ToInt32(Me.label1.Text) - 1).ToString()
    		dtInfo = LoadData(Convert.ToInt32(Me.label1.Text))
    		Me.dataGridView1.DataSource = Nothing
    		Me.dataGridView1.DataSource = dtInfo
    	End If
    End Sub
    

    If you want to keep track of what’s loaded there, you can write log for it. But IO operation will reduce this application’s performance. I suggest logging the record which failed to display or something else.

    Have a nice time!

    Sincerely,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Monday, February 17, 2014 5:02 AM

All replies

  • First of all, don't use controls which contains more then 60 lines of data. It is only bullying the end user, try to give them information instead of data.

    If you have to page in the datagridview you can use this sample.

    http://www.vb-tips.com/PageDataGridView.aspx

    And don't forget this piece of code.

    datagridview1.suspendlayout


    Success
    Cor

    Sunday, February 16, 2014 8:18 AM
  • Again, I don't agree with Cor.  I use DataGridView with 1,000 of rows without any issues except it may take a long time initially to create the DGV.  When an application starts there is no data in the DGV and must be loaded.  An application doesn't store the DGV data from the last time it was run.

    jdweng

    Sunday, February 16, 2014 10:31 AM
  • Again, I don't agree with Cor.  I use DataGridView with 1,000 of rows without any issues except it may take a long time initially to create the DGV.  When an application starts there is no data in the DGV and must be loaded.  An application doesn't store the DGV data from the last time it was run.

    jdweng

    Maybe, however that shows probably only that I create applications with end users in my view and you seem to have a different goal.

    Success
    Cor

    Sunday, February 16, 2014 10:39 AM
  • I have an application where its a form with a tabcontrol.

    i'll have about 14 tabpages and a datagridview on each tab.  When the applaction is first opened up, the datagradview with lots of data takes up to 10 seconds to draw itself out. 

    How can I figure out what is causing this?  Seems like with the data already there in the grid, it should not take as long.


    How much data are you loading? 1000 rows of 10 columns of bitmaps? Where is the data coming from? Maybe show the code if not too complex.

    Assuming it is nothing in your code causing delays, maybe you can find ways to work around the startup time issues. For example, by loading the data when the tab is selected the first time by the user. Then you have 1/14th of the time waiting for each tab. Or, you could also have the program start up and then load the views in the background by using a timer and separate threads etc. Maybe only load parts of the data at first, then more if the user scrolls the view.

    We can debate the philosophy or try to find a solution. Either way, seems we don't have enough info to say much. 

    Sunday, February 16, 2014 12:03 PM
  • PS I assume you have timed the loading of the grid separately? It takes many seconds just to load the VS .net application things the first time you run your app on a system.

    Always hard to know how advanced a poster is.


    Sunday, February 16, 2014 12:57 PM
  • Thanks for all the insights. maybe I can provide a bit more information.

    I need to load all the data into the datagridview, because I want to all the user to use this as an editing tool.   Some of the datagridviews only have a few rows, where as some of the others could have a 2000 to 5000 rows.  I would seem logical to control the number of rows to be shown in a datagridview(something I suppose I should try and figure out). 

    I am loading the dataviewgrids from either a csv file or xml files.  The app startup is not the issue as I don't do anything until the user selects which file to load first.

    My orginal intent was to load the csv file which is a very large file, and parse the file to break down into IO Data types.  Once that is done, import into an access database. Normally, I would just edit the file in Excel, however, I have issues with Excel when I start to sort and filter data.

    Now I am looking at the possibility of just using this application to modify the data without the need for Access.  But I have concerns about proformance issues, and that is the part I am testing now. 

    so, it sounds like I need to control the number of records displayed on large datagridviews.  Any idea's or thoughts on this, and how to do this with the best end user performance?

    Brian

    Sunday, February 16, 2014 2:05 PM
  • Thanks for all the insights. maybe I can provide a bit more information.

    I need to load all the data into the datagridview, because I want to all the user to use this as an editing tool.   Some of the datagridviews only have a few rows, where as some of the others could have a 2000 to 5000 rows.  I would seem logical to control the number of rows to be shown in a datagridview(something I suppose I should try and figure out). 

    I am loading the dataviewgrids from either a csv file or xml files.  The app startup is not the issue as I don't do anything until the user selects which file to load first.

    My orginal intent was to load the csv file which is a very large file, and parse the file to break down into IO Data types.  Once that is done, import into an access database. Normally, I would just edit the file in Excel, however, I have issues with Excel when I start to sort and filter data.

    Now I am looking at the possibility of just using this application to modify the data without the need for Access.  But I have concerns about proformance issues, and that is the part I am testing now. 

    so, it sounds like I need to control the number of records displayed on large datagridviews.  Any idea's or thoughts on this, and how to do this with the best end user performance?

    Brian

    Can you preprocess the original csv file into the parts you need, before your app starts even? So your app is dealing with something faster to read. How about change the app making the csv file?

    I dont know the gridview very well. However, you are on the right track. It seems you can use the Control.AutoScrollOffset property to determine when the users scrolls down to the end of the rows and then load another 100 rows or something.

    If you use ownerdraw you could do the same thing ie when drawing the last rows, load more data. In fact I can envision only having 100 rows in the grid at a time and just drawing the data as it is scrolled by the user. ie if they scroll to row 1000 then only have the data from row 950 to 1050 in the grid. Of course these are wild just ideas I have not tried.

    Maybe someone else will have better working examples.

    Sunday, February 16, 2014 3:27 PM
  • I don't want to preprocess my data on the csv, as it generated by an factory automation package. The length of time processing that does not concern me to much, as I have a callback to the form to notify the user of processing. For a Very large application, it only takes a minute or so.

    The main issue is the proformace when the user selects one of the tabs to view the data in the grid.  I will have to start venturing down that road soon :)

    the issue I am having now, I'll put in a different post.  

    But if anyone one else has some idea's on how to load a few hundred records at a time into a datagridview and keep track of whats loaded there, and how to fetch the next or previous 100 rows.

    Sunday, February 16, 2014 3:38 PM
  • Hi,

    >> But if anyone one else has some idea on how to load a few hundred records at a time into a data grid view and keep track of what’s loaded there, and how to fetch the next or previous 100 rows.<<

    In my view, we can use stored procedures and paging to achieve this goal. I created a general sample to achieve this goal,

    Stored procedure:

    CREATE PROCEDURE dbo.pagination 
     (
     @PageSize int = 10,
     @CurrentPageIndex int=1 
     )
     
    AS
       declare @index int
     if(@CurrentPageIndex=1)
       begin
          EXEC( 'SELECT TOP ' + @PageSize +  '* from Orders ')
       end
     else
       begin
       set @index= (@CurrentPageIndex-1) * @PageSize
            EXEC( 'SELECT TOP ' + @PageSize +  '* from Orders where OrderId not in '
            +'(select top '+ @index +'OrderId from Orders ) ')
          end
     RETURN

    VB.NET Code:

    Private Const pageSize As Integer = 10
    
    Private dtInfo As DataTable = Nothing
    Protected Function ConnectStr() As String
    
    	Dim _connnectionStr As String = [String].Format("Data Source=localhost;AttachDbFilename={0};Integrated Security=True", "F:\xyt\MyProject\DataGridView\DataGridViewAndCheckBox\DataGridViewAndCheckBox\bin\Debug\b2bdb_Data.MDF")
    	'connection string
    	Return _connnectionStr
    End Function
    
    Private Function LoadData(PageIndex As Integer) As DataTable
    	Dim con As New SqlConnection(Me.ConnectStr())
    	Dim cmd As New SqlCommand("pagination", con)
    	cmd.CommandType = CommandType.StoredProcedure
    	con.Open()
    	cmd.Parameters.Add(New SqlParameter("@PageSize", SqlDbType.Int, 4))
    	cmd.Parameters("@PageSize").Value = pageSize
    	cmd.Parameters.Add(New SqlParameter("@CurrentPageIndex", SqlDbType.Int, 4))
    	cmd.Parameters("@CurrentPageIndex").Value = PageIndex
    
    	Dim dt As New DataTable()
    	Dim adapter As New SqlDataAdapter(cmd)
    	adapter.Fill(dt)
    
    	con.Close()
    	Return dt
    
    End Function
    
    Private Sub Form1_Load(sender As Object, e As EventArgs)
    	dtInfo = LoadData(1)
    	Me.dataGridView1.DataSource = dtInfo
    	Me.label1.Text = Convert.ToString(1)
    
    End Sub
    
    Private Sub btnNext_Click(sender As Object, e As EventArgs)
    	Me.label1.Text = (Convert.ToInt32(Me.label1.Text) + 1).ToString()
    	dtInfo = LoadData(Convert.ToInt32(Me.label1.Text))
    	If dtInfo.Rows.Count = 0 Then
    		'This is the last page.
    		Me.label1.Text = (Convert.ToInt32(Me.label1.Text) - 1).ToString()
    		MessageBox.Show("This is the last page.")
    	Else
    		Me.dataGridView1.DataSource = Nothing
    		Me.dataGridView1.DataSource = dtInfo
    	End If
    End Sub
    
    Private Sub btnPrevious_Click(sender As Object, e As EventArgs)
    
    	If Me.label1.Text = "1" Then
    		MessageBox.Show("This is first page")
    		Return
    	Else
    		Me.label1.Text = (Convert.ToInt32(Me.label1.Text) - 1).ToString()
    		dtInfo = LoadData(Convert.ToInt32(Me.label1.Text))
    		Me.dataGridView1.DataSource = Nothing
    		Me.dataGridView1.DataSource = dtInfo
    	End If
    End Sub
    

    If you want to keep track of what’s loaded there, you can write log for it. But IO operation will reduce this application’s performance. I suggest logging the record which failed to display or something else.

    Have a nice time!

    Sincerely,


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Monday, February 17, 2014 5:02 AM
  • What you mean, I've given you that in my first reply, what is wrong with that?

    Success
    Cor

    Monday, February 17, 2014 7:29 AM
  • @Cor, I am very sorry about that.  :) I will take care next time! Sorry again.

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Monday, February 17, 2014 7:33 AM
  • @Cor, I am very sorry about that.  :) I will take care next time! Sorry again.

    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    @Jimmy, 

    I was replying to Landlord, not to you, no problem, because of your code I was attended.



    Success
    Cor


    Monday, February 17, 2014 9:03 AM