Chắc hẳn mọi người khi đang lướt facebook và kéo xuống tới cuối trang thì nó tự động load thêm tin tức mới. Làm như thế giảm bớt được số lượng dữ liệu tạm gọi là dư thừa chưa cần thiết đến. Vì thế mình cũng muốn áp dụng nó vào trong cái project WinForm của mình để hoạt động cho hiệu quả Wink


Chuẩn bị


Đầu tiên mình cần chuẩn bị 1 ít dữ liệu giả để mô phỏng nó. Ở đây mình sẽ tạo 2 cái biến với kiểu DataTable vì mình không muốn dùng đến Database ở phần mô phỏng này.


private DataTable dt; // Coi như đây là toàn bộ dữ liệu nằm trong table của Database
private DataTable temp; // Coi như đây là toàn bộ dữ liệu đang có trên DataGridView

void createColumn(ref DataTable table) // tạo column cho 2 cái DataTable
{
    table = new DataTable();
    table.Columns.Add("ID");
    table.Columns.Add("Name");
}

public Form1()
{
    InitializeComponent();

    createColumn(ref dt);
    createColumn(ref temp);

    dataGridView1.DataSource = dt; // gán trước để nó có sẵn Column để lúc add thêm rows không báo lỗi
    for(int i = 0; i < 10000; i++)
    {
        dt.Rows.Add(i, "Name " + i);
    }

    addRows(); // thêm 1 ít dữ liệu đầu tiên
}

Thêm dữ liệu


private const int limit = 20; // giới hạn 20 rows mỗi lần load thêm
private int current = 0; // xác định số rows hiện tại
void addRows()
{
    int total_after = limit + current; // Số rows sau khi tăng thêm 
    while (current < total_after) // loop
    {
        if (dt.Rows.Count >= total_after) // Nếu còn dữ liệu thì load tiếp
        {
            DataRow dr = dt.Rows[current++];
            temp.Rows.Add(dr[0], dr[1]);
        }
       else
             break;
    }
    dataGridView1.DataSource = temp;
}

 


Sự kiện Scroll


private void dataGridView1_Scroll(object sender, ScrollEventArgs e)
{
   if(temp.Rows.Count - dataGridView1.FirstDisplayedScrollingRowIndex <= 15 && current < dt.Rows.Count) // kiểm tra điều kiện để load tiếp
    {
      addRows();
    }
}

 


Thử nghiệm


Bạn chạy thử xem, nó sẽ hoạt động. Nhưng chỉ hoạt động đúng ý muốn khi bạn scroll nhỏ nhẹ thôi, bạn mà scroll 1 phát xuống cuối thì bảo đảm nó loop Smile)


Fix Loop


//Ẩn hiện cái ScrollBars
ScrollBars gridscrollbar;
private void HideScrollBar()
{
    gridscrollbar = dataGridView1.ScrollBars;
    dataGridView1.ScrollBars = ScrollBars.None;
}
private void ShowScrollBars()
{
    dataGridView1.ScrollBars = gridscrollbar;
}

 


Sau đó là method lấy số Rows đang hiển thị


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

 


Tiếp theo là phải cải tiến method addRows()


DateTime lastLoading; // Lưu lại thời gian lần trước load
int firstVisibleRow; // Rows đầu tiên đang hiển thị
void addRows()
{
    HideScrollBar();
    lastLoading = DateTime.Now;
    int total_after = limit + current;
    while (current < total_after)
    {
        if (dt.Rows.Count >= total_after)
        {
            DataRow dr = dt.Rows[current++];

            temp.Rows.Add(dr[0], dr[1]);
        }
        else
            break;
    }
    if (firstVisibleRow > -1)
    {
        ShowScrollBars();
        dataGridView1.FirstDisplayedScrollingRowIndex = firstVisibleRow;
    }
    dataGridView1.DataSource = temp;
}

 


Về biến firstVisibleRow bạn có thể hiểu như sau



Biến firstVisibleRow sẽ lưu Row ID của Row có ID là số 6 và Name 6 trong hình. Khi scroll xuống thì nó sẽ thay đổi.


Cải tiến event Scroll để chống Auto Scroll


private void dataGridView1_Scroll(object sender, ScrollEventArgs e)
{
    if (e.Type == ScrollEventType.SmallIncrement || e.Type == ScrollEventType.LargeIncrement) // Kiểm tra scroll down
    {
        if (e.NewValue >= dataGridView1.Rows.Count - GetDisplayedRowsCount())
        {
            TimeSpan ts = DateTime.Now - lastLoading;
            if (ts.TotalMilliseconds > 100)
            {
                firstVisibleRow = e.NewValue;
                addRows();
            }
            else
            {
                dataGridView1.FirstDisplayedScrollingRowIndex = e.OldValue;
            }
        }
    }
}

Xong rồi Wink Các bạn có thẻ test thử. Nếu có thắc mắc hay vấn đề gì cứ comment bên dưới nhé Wink