RSS

Catch scroll to end of DataGridView in C#

03 Jan
How to catch when the user scrolls to the bottom of the dataGridView, so I can load more results:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

namespace WindowsApplication30
{

    public partial class Form1 : Form
    {

        private DateTime lastLoading;
        private int firstVisibleRow;
        private ScrollBars gridScrollBars;

        public Form1()
        {
            InitializeComponent();

            //attach scroll event.
            dataGridView1.Scroll += new ScrollEventHandler(dataGridView1_Scroll);

            //load firs 100 rows.
            LoadRows();
        }

        private void HideScrollBars()
        {
            gridScrollBars = dataGridView1.ScrollBars;
            dataGridView1.ScrollBars = ScrollBars.None;
        }

        private void ShowScrollBars()
        {
            dataGridView1.ScrollBars = gridScrollBars;
        }

        private int GetDisplayedRowsCount()
        {
            int count = dataGridView1.Rows[dataGridView1.FirstDisplayedScrollingRowIndex].Height;
            count = dataGridView1.Height / count;
            return count;
        }

        private void LoadRows()
        {
            HideScrollBars();

            System.Diagnostics.Debug.WriteLine("Load data");
            lastLoading = DateTime.Now;

            //create rows
            for (int i = 0; i < 100; i++)
            {
                int n =dataGridView1.Rows.Add();
                dataGridView1.Rows[n].Cells[0].Value = "Row - " + n.ToString();
            }

            //reset displayed row
            if (firstVisibleRow > -1)
            {
                ShowScrollBars();
                dataGridView1.FirstDisplayedScrollingRowIndex = firstVisibleRow;
            }
        }

        void dataGridView1_Scroll(object sender, ScrollEventArgs e)
        {
            if (e.Type == ScrollEventType.SmallIncrement || e.Type == ScrollEventType.LargeIncrement)
            {
                if (e.NewValue >= dataGridView1.Rows.Count - GetDisplayedRowsCount())
                {
                    //prevent loading from autoscroll.
                    TimeSpan ts = DateTime.Now - lastLoading;
                    if (ts.TotalMilliseconds > 100)
                    {
                        firstVisibleRow = e.NewValue;
                        LoadRows();
                    }
                    else
                    {
                        dataGridView1.FirstDisplayedScrollingRowIndex = e.OldValue;
                    }
                }
            }
        }
    }
}

private DateTime lastLoading;
In this variable I save last loading time and it is used to prevent “loading while loading” (scroll event is fired while loading because of the automatic scrolling) . Interval between loading in this example is 100 ms.

  private int firstVisibleRow;

In this variable I save first visible row index before loading and set datagridview first visible row after loading. This is also used because of the automatic scrolling.

        private ScrollBars gridScrollBars;

In this variable I save datagridview scrollbars property and it is used to force scrollbar update because scrollbar is not updated after loading.

   //attach scroll event.
            dataGridView1.Scroll += new ScrollEventHandler(dataGridView1_Scroll);

In this line I just atach datagridview scroll event.

            //load firs 100 rows.
            LoadRows();

In this line I load first 100 rows on startup. I use this method because in my test application I don’t have any data and this simulate real loading.

        private void HideScrollBars()
        {
            gridScrollBars = dataGridView1.ScrollBars;
            dataGridView1.ScrollBars = ScrollBars.None;
        }

In this method I save datagridview scrollbars in variable and hide scrollbars. (update scrollbars after loading).

    private void ShowScrollBars()
        {
            dataGridView1.ScrollBars = gridScrollBars;
        }

In this method I show datagridview scrollbars. (update scrollbars after loading).

        private int GetDisplayedRowsCount()
        {
            int count = dataGridView1.Rows[dataGridView1.FirstDisplayedScrollingRowIndex].Height;
            count = dataGridView1.Height / count;
            return count;
        }

In this method I calculate number of visible rows. This is needed because value in datagridview scroll event (e.NewValue) is index of first visible row in datagridview.

        private void LoadRows()
        {
            HideScrollBars();

            System.Diagnostics.Debug.WriteLine("Load data");
            lastLoading = DateTime.Now;

            //create rows
            for (int i = 0; i < 100; i++)
            {
                int n =dataGridView1.Rows.Add();
                dataGridView1.Rows[n].Cells[0].Value = "Row - " + n.ToString();
            }

            //reset displayed row
            if (firstVisibleRow > -1)
            {
                ShowScrollBars();
                dataGridView1.FirstDisplayedScrollingRowIndex = firstVisibleRow;
            }
        }

In this method I create rows in grid and you should replace for loop with your load data. You need code which is before and after loop.

    void dataGridView1_Scroll(object sender, ScrollEventArgs e)
        {
            if (e.Type == ScrollEventType.SmallIncrement || e.Type == ScrollEventType.LargeIncrement)
            {
                if (e.NewValue >= dataGridView1.Rows.Count - GetDisplayedRowsCount())
                {
                    //prevent loading from autoscroll.
                    TimeSpan ts = DateTime.Now - lastLoading;
                    if (ts.TotalMilliseconds > 100)
                    {
                        firstVisibleRow = e.NewValue;
                        LoadRows();
                    }
                    else
                    {
                        dataGridView1.FirstDisplayedScrollingRowIndex = e.OldValue;
                    }
                }
            }

In this event handler I do few thing:

– Check scroll event type – because we need to load data only in scroll down

– Get new value from event args (e.NewValue) – this is index of first displayed row in grid

– Get displayed rows count – rows in view

– Check if new value is bigger or equal to last row in grid – if yes.. then load more data

– Check last loading time – prevent “loading from loading” (workaround for grid autoscroll)

Referenced by: http://social.msdn.microsoft.com/Forums/en-SG/Vsexpressvcs/thread/4a882eff-f6dd-4d8f-86d9-e3d85947522e

Advertisements
 
2 Comments

Posted by on January 3, 2012 in C#, Window Application

 

2 responses to “Catch scroll to end of DataGridView in C#

  1. johnnytaj

    July 11, 2012 at 5:17 PM

    So it is clear from the article that almost each of the aforementioned lists has Clear() method, that has a specific action when invoked on a certain collection. Specifically, Header.Grouped Columns.Clear() removes data grouping in header of a grid.
    http://www.dapfor.com/en/net-suite/net-grid/features/performance

     
  2. Saeed

    December 7, 2012 at 11:45 AM

    I am getting error in LoadRows function.At the line

    int n =dataGridView1.Rows.Add();

    ” No row can be added to a DataGridView control that does not have columns. Columns must be added first”. How to solve this problem.

     

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: