Lazy Loading với DataGridView WinForm
C#
28
Winform
1
White

Phạm Quốc Thắng viết ngày 01/06/2016

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ả :smile:

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 = new DataTable(); // Coi như đây là toàn bộ dữ liệu nằm trong table của Database
private DataTable temp = new DataTable(); // Coi như đây là toàn bộ dữ liệu đang có trên DataGridView

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

public Form1()
{
    InitializeComponent();

    createColumn(dt);
    createColumn(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
alt text
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 :smile: 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é :smile:

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

Phạm Quốc Thắng

15 bài viết.
48 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Cùng một tác giả
White
22 34
Chuẩn bị Một link bài hát / video từ mp3.zing.vn Nghịch ngợm Cũng vì dạo này mình hơi rảnh rỗi với có một chút phiền phức khi đang thưởng thức ...
Phạm Quốc Thắng viết gần 5 năm trước
22 34
White
10 1
Bài viết này mình sẽ trình bày những thứ cơ bản về cú pháp với Swift. Bài viết sẽ gồm các phần Phần 1 Hằng và Biến Ghi chú Dấu chấm phẩy S...
Phạm Quốc Thắng viết gần 5 năm trước
10 1
White
7 1
Disclaimer: Mình đã thông báo bug này cho support tenlua.vn 2 lần, và họ đã fix bằng cách upgrade 1 bản api ver 2, tuy nhiên api ver 1 vẫn hoạt độn...
Phạm Quốc Thắng viết gần 5 năm trước
7 1
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
15 bài viết.
48 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!