• Vui lòng đọc nội qui diễn đàn để tránh bị xóa bài viết
  • Tìm kiếm trước khi đặt câu hỏi

[VB.NET] Hướng dẫn phân trang trong DataGridView

Các bài viết hướng dẫn về Visual Basic .NET và C#

Moderators: tungcan5diop, QUANITGROBEST

User avatar
Kasper
Guru
Guru
Posts: 1063
Joined: Fri 16/05/2008 10:54 am
Has thanked: 2 times
Been thanked: 76 times
Contact:

[VB.NET] Hướng dẫn phân trang trong DataGridView

Postby Kasper » Thu 08/04/2010 10:16 am

Tên bài viết: Hướng dẫn phân trang trong DataGridView
Tác giả: Kasper
Cấp độ bài viết: Chưa đánh giá
Tóm tắt:



Bài viết này sẽ hướng dẫn các bạn phân trang cho DataGridView.
Cần: 1 form, 1 datagridview, 3 button: btnLoad, btnBack, btnNext. 1 Label: lblPage: hiển thị" "trang hiện tại/tổng số trang"

Khai báo các biến liên quan
  1.     Dim mCurrentPage As Integer ' Trang hiện tại
  2.     Dim mNumPages As Integer ' Tổng số trang
  3.     Const ITEMperPAGE As Integer = 15 ' Số Item cần hiển thị trên một trang
  4.  


Để có dữ liệu thao tác tui sẽ giả lập dữ liệu, phần này các bạn thay thế bằng dữ liệu của mình được truy vấn từ csdl.
Code trong btnLoad
[vbnet]
Private Sub btnLoad_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnLoad.Click
' Giả lập dữ liệu
Dim dt As New DataTable
dt.Columns.Add("STT")
dt.Columns.Add("Name")
dt.Columns.Add("Date")
Dim i As Integer
For i = 1 To 107
dt.Rows.Add(i, "Tran Van " & Chr(i + 64), Format(Now.Date.AddDays(i), "dd/MM/yyyy"))
Next
' Cho hiển thị trang đầu tiên, ở đây tui hiển thị 15 item/1 trang.
' Ta sẽ dùng method RowFilter của DataTable để lọc dữ liệu hiển thị
' Tui sẽ dựa vào cột STT để xét điều kiện lọc, các bạn có thể thay thế theo ý mình.
DataGridView1.DataSource = dt
mCurrentPage = 1
mNumPages = Math.Round(dt.Rows.Count / ITEMperPAGE + 0.5) ' Xác định tổng số trang cần chia
lblPage.Text = "1/" & mNumPages
Dim gridTable As DataTable = CType(DataGridView1.DataSource, DataTable)
gridTable.DefaultView.RowFilter = "STT <= " & ITEMperPAGE * mCurrentPage ' Lọc phân trang theo điều kiện.
btnNext.Enabled = True
End Sub
[/vbnet]

Xong phần giả lập dữ liệu và hiển thị trang đầu tiên, giờ ta sẽ viết code cho nút Next và Back.
1. Nút Next: mỗi lần click, ta sẽ tăng trang hiện tại lên 1, xét xem trang hiện tại còn <= tổng số trang hay không, nếu đúng ta tiến hành lọc dữ liệu.
[vbnet]
Private Sub btnNext_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnNext.Click
mCurrentPage += 1
If mCurrentPage <= mNumPages Then
Dim gridTable As DataTable = CType(DataGridView1.DataSource, DataTable)
gridTable.DefaultView.RowFilter = "STT > " & ITEMperPAGE * (mCurrentPage - 1) & " AND STT <= " & ITEMperPAGE * mCurrentPage
btnBack.Enabled = True
lblPage.Text = mCurrentPage & "/" & mNumPages
End If
If mCurrentPage = mNumPages Then
btnBack.Enabled = True
btnNext.Enabled = False
End If
End Sub
[/vbnet]

2. Nút Back: mỗi lần click, ta sẽ giảm trang hiện tại xuống 1, xét xem trang hiện tại còn >= trang đầu tiên hay không, nếu đúng ta tiến hành lọc dữ liệu.
[vbnet]
Private Sub btnBack_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnBack.Click
mCurrentPage -= 1
If mCurrentPage >= 1 Then
Dim gridTable As DataTable = CType(DataGridView1.DataSource, DataTable)
gridTable.DefaultView.RowFilter = "STT > " & ITEMperPAGE * (mCurrentPage - 1) & " AND STT <= " & ITEMperPAGE * mCurrentPage
btnNext.Enabled = True
lblPage.Text = mCurrentPage & "/" & mNumPages
End If
If mCurrentPage = 1 Then
btnBack.Enabled = False
btnNext.Enabled = True
End If
End Sub
[/vbnet]

Chúc các bạn thành công!
Attachments
Chiatrang.gif
Chiatrang.zip
(69.82 KiB) Downloaded 1976 times


Lành tợ tòng, ác tợ hoa,
Nhà hòa muôn việc đều nên.

amrsau
Posts: 1
Joined: Fri 09/07/2010 4:22 pm

Re: [VB.NET] Hướng dẫn phân trang trong DataGridView

Postby amrsau » Fri 09/07/2010 9:53 pm

Bài này vẫn hơi lỗi 1 tý!

Nếu khi ấn vào load xong,bạn cứ click vào nút back vài cái xem sao?Sau đó bạn click vào nút nẽt và xem kết quả trên trang hiển thị!

Đây là ý kiến của mình:Bạn nên để btnBack.Enable=false khi Load và khi click vào Next thì btnBack.enable=true

User avatar
Kasper
Guru
Guru
Posts: 1063
Joined: Fri 16/05/2008 10:54 am
Has thanked: 2 times
Been thanked: 76 times
Contact:

Re: [VB.NET] Hướng dẫn phân trang trong DataGridView

Postby Kasper » Mon 12/07/2010 11:58 am

amrsau wrote:Bài này vẫn hơi lỗi 1 tý!

Nếu khi ấn vào load xong,bạn cứ click vào nút back vài cái xem sao?Sau đó bạn click vào nút nẽt và xem kết quả trên trang hiển thị!

Đây là ý kiến của mình:Bạn nên để btnBack.Enable=false khi Load và khi click vào Next thì btnBack.enable=true


Cái này có rồi mà. Vừa load xong làm gì bấm được nút Back khi nó Disable mà lỗi hả bạn? :-/
Lành tợ tòng, ác tợ hoa,
Nhà hòa muôn việc đều nên.

User avatar
vuathongtin
Điều hành viên
Điều hành viên
Posts: 1028
Joined: Sun 02/05/2010 10:03 pm
Location: Xứ sở DG
Has thanked: 2 times
Been thanked: 105 times
Contact:

Re: [VB.NET] Hướng dẫn phân trang trong DataGridView

Postby vuathongtin » Tue 13/07/2010 9:46 am

Mình xin góp ý 1 chút nhen .
1. Bạn nên đưa biến datatable khai báo tạm :
  1. Dim gridTable As DataTable
lên làm biến toàn cục
Khi đó :
Next :
[vbnet]If mCurrentPage < mNumPages Then
mCurrentPage += 1
lblPage.Text = mCurrentPage & "/" & mNumPages
gridTable.DefaultView.RowFilter = "STT>" & ITEMperPAGE * (mCurrentPage - 1) & " and STT<=" & ITEMperPAGE * mCurrentPage & ""
End If[/vbnet]

Back :
[vbnet] If mCurrentPage > 1 Then
mCurrentPage -= 1
lbl_page.Text = mCurrentPage & "/" & mNumPages
gridTable.DefaultView.RowFilter = "STT>" & ITEMperPAGE * (mCurrentPage - 1) & " and STT<=" & ITEMperPAGE * mCurrentPage & ""

End If[/vbnet]

Ví dụ : Code phân trang trong Project của mình :

[vbnet]Imports System.Data.OleDb

Public Class frm_dssinhvien
Dim mCurrentPage As Integer
Dim mNumPages As Integer
Const ITEMperPAGE As Integer = 7

Dim con As New OleDbConnection
Dim da_sinhvien As New OleDbDataAdapter
Dim dt_sinhvien As New DataTable

Public dt_temp As DataTable

Sub ketnoi()
If con.State = ConnectionState.Closed Then
con.ConnectionString = "Provider=Microsoft.Jet.OleDB.4.0;" & "data source=" & Application.StartupPath & "\QUAN_LY_SINH_VIEN.mdb"
con.Open()
End If
End Sub

Private Sub frm_dssinhvien_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
ketnoi()
da_sinhvien = New OleDbDataAdapter("Select *from SINHVIEN", con)
da_sinhvien.Fill(dt_sinhvien)
dgv_sinhvien.DataSource = dt_sinhvien

dt_sinhvien.Columns.Add("STT")
For i As Integer = 0 To dt_sinhvien.Rows.Count - 1
dgv_sinhvien.Rows(i).Cells("STT").Value = i
Next

' Tinh so trang can chia
mCurrentPage = 1
mNumPages = Math.Round(dt_sinhvien.Rows.Count / ITEMperPAGE + 0.5)
lbl_page.Text = "1/" & mNumPages

dt_temp = (CType(dgv_sinhvien.DataSource, DataTable))
dt_temp.DefaultView.RowFilter = "STT<=" & ITEMperPAGE * mCurrentPage & ""
End Sub

Private Sub btn_next_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_next.Click
If mCurrentPage < mNumPages Then
mCurrentPage += 1
lbl_page.Text = mCurrentPage & "/" & mNumPages
dt_temp.DefaultView.RowFilter = "STT>" & ITEMperPAGE * (mCurrentPage - 1) & " and STT<=" & ITEMperPAGE * mCurrentPage & ""
End If
End Sub

Private Sub btn_previous_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btn_previous.Click
If mCurrentPage > 1 Then
mCurrentPage -= 1
lbl_page.Text = mCurrentPage & "/" & mNumPages
dt_temp.DefaultView.RowFilter = "STT>" & ITEMperPAGE * (mCurrentPage - 1) & " and STT<=" & ITEMperPAGE * mCurrentPage & ""

End If
End Sub
End Class
[/vbnet]


Mình xin nếu tóm lược các bước để phân trang trong datagridview để các bạn dễ hình dung:
1. Khai báo các biến toàn cục sau :
[vbnet] Dim mCurrentPage As Integer ' vị trí trang hiện tại
Dim mNumPages As Integer ' số trang = tổng số record (= dt.row.count) / số record cần hiển thị
Const ITEMperPAGE As Integer = 7 'Số Record cần hiển thị ở mỗi trang
dim dt_temp As DataTable ' biến datatable (tạm) dùng để hiển thị phân trang trong datagrid
[/vbnet]
2. Tính số trang cần chia
[vbnet] mCurrentPage = 1
mNumPages = Math.Round(dt_sinhvien.Rows.Count / ITEMperPAGE + 0.5) 'Dùng toán tử Round để làm tròn số[/vbnet]

3.
3.1 (Bước này không cần thiết)
Add thêm cột "STT" để lọc số record cần hiển thị
[vbnet]dt.Columns.Add("STT")
For i As Integer = 0 To dt.Rows.Count - 1
datagridview1.Rows(i).Cells("STT").Value = i
Next[/vbnet]

3.2.
Chuyển dữ liệu từ Datagridview vào biến dt_temp
bằng hàm Ctype
[vbnet] dt_temp = (CType(datagridview1.DataSource, DataTable))[/vbnet]

4. Dùng phương thức RowFilter để Show dữ liệu với điều kiện cho trước
dt_temp.DefaultView.RowFilter = "STT<=" & ITEMperPAGE * mCurrentPage & ""

Khi next (hoăc Back):

1. Tăng (hoặc giảm) vị trí trang hiện tại lên 1
Dùng phương thức Rowfilter để hiển thị dữ liệu với điều kiện
STT>" & ITEMperPAGE * (mCurrentPage - 1) & " and STT<=" & ITEMperPAGE * mCurrentPage &

2. Tạo các điều kiện ràng buộc khi Next (hoặc Back)
Next : khi giá trị trang hiện tại < số trang :

Code: Select all

 mCurrentPage < mNumPages

Back : chỉ khi nào giá trị trang hiện tại > 1 :

Code: Select all

mCurrentPage > 1
Attachments
QLSV.rar
(71.61 KiB) Downloaded 712 times
Last edited by vuathongtin on Tue 13/07/2010 10:16 am, edited 1 time in total.
Bùi Thành Nhân
* Chuyên gia MMO
congtacvien.online

User avatar
thuccads
Thành viên tích cực
Thành viên tích cực
Posts: 143
Joined: Mon 01/02/2010 8:35 am
Location: Hà Nội--->Sài Gòn
Been thanked: 1 time
Contact:

Re: [VB.NET] Hướng dẫn phân trang trong DataGridView

Postby thuccads » Tue 13/07/2010 10:06 am

Nếu SQL 2005 trở lên thì bạn dùng hàm ROW_NUMBER() đỡ phải Add columns.

User avatar
Kasper
Guru
Guru
Posts: 1063
Joined: Fri 16/05/2008 10:54 am
Has thanked: 2 times
Been thanked: 76 times
Contact:

Re: [VB.NET] Hướng dẫn phân trang trong DataGridView

Postby Kasper » Tue 13/07/2010 11:21 am

Mình xin góp ý 1 chút nhen .
1. Bạn nên đưa biến datatable khai báo tạm lên làm biến toàn cục


Biến toàn cục hay biến cục bộ chỗ này chúng ta nên suy xét kỹ hơn.
1. Biến cục bộ:
Mỗi lần click nút back hoặc next: lấy datasource của DGV đổ vào datatable, tốc độ của thao tác này nhanh chậm tùy thuộc vào số row nhiều hay ít, nhưng được lợi là thoát khỏi hàm thì giải phóng luôn bộ nhớ.
Có ai test giùm câu lệnh sau đây mất bi nhiêu time với số lượng row khác nhau: 1K, 10K, 100K, 1.000K, ...
  1. Dim gridTable As DataTable = CType(DataGridView1.DataSource, DataTable)
  2.  


2. Biến toàn cục:
Chỉ lấy datasource 1 lần duy nhất, nhưng chương trình sẽ chiếm nhiều bộ nhớ để lưu trữ datatable cho đến khi đóng form này lại.

Vậy nếu để tối ưu chương trình, ta nên cân nhắc kỹ rồi sử dụng thôi :D
Lành tợ tòng, ác tợ hoa,
Nhà hòa muôn việc đều nên.


Return to “[.NET] Bài viết hướng dẫn”

Who is online

Users browsing this forum: No registered users and 1 guest