Điều khiển GridView trong ASP.NET có khả năng phân trang được xây dựng trong chức năng hỗ trợ phân trang cơ bản. Bạn có thể sử dụng giao diện người dùng phân trang mặc định (giao diện người dùng) hoặc tạo ra giao diện phân trang tùy chỉnh.
Trong bài viết này, tôi sẽ thảo luận về ví dụ tùy chỉnh phân trang. Phân trang tùy chỉnh có một nhược điểm hiệu suất lớn. Nếu bạn có 10.000 hồ sơ trong bảng, bạn phải giao toàn bộ dữ liệu cho GridView và GridView xác định hồ sơ nó hiển thị và sẽ loại bỏ kết quả. Có nghĩa là, nếu Grid được phân trang thông qua tổng cộng 10.000 hồ sơ, cho thấy 50 hồ sơ cho mỗi trang, trên mỗi trang yêu cầu tất cả 10.000 hồ sơ sẽ được trả lại từ các cơ sở dữ liệu, nhưng chỉ có 50 người thích hợp sẽ được hiển thị. Với Custom Paging, chúng ta không cần phải lấy tất cả các hồ sơ cùng một lúc. Chúng ta có thể làm được từng trang phụ thuộc vào chỉ số trang. Trong kịch bản trên, chúng ta chỉ nhận được 50 hồ sơ tại một thời điểm từ cơ sở dữ liệu.
Kết nối Cơ sở dữ liệu
Mở web.config và thêm mục sau đây để kết nối các chuỗi
<add name="Sql" connectionString="Data Source=<SERVERNAME>;
Initial Catalog= TEST;User=testuser;Password=testuser;"
providerName="System.Data.SqlClient"/>
Trang Design
Bởi phân trang mặc định bị vô hiệu hóa trong GridView, vì vậy không phải lo lắng. Chúng ta đã thêm một số cột bị ràng buộc để hiển thị dữ liệu sản phẩm. Áp dụng một số định dạng làm cho GridView nhìn đẹp và sạch sẽ.
<asp:gridview ID="gvProducts"
BorderColor="White" BorderStyle="Ridge"
CellSpacing="1" CellPadding="3" GridLines="None"
BackColor="White" BorderWidth="2px"
AutoGenerateColumns="False"
runat="server" DataKeyNames="ProductID">
<Columns>
<asp:BoundField DataField="ProductID" HeaderText="Product ID">
<HeaderStyle HorizontalAlign="Left" Width="150px"/>
</asp:BoundField>
<asp:BoundField DataField="ProductNumber" HeaderText="Product Number">
<HeaderStyle HorizontalAlign="Left" Width="150px" />
<ItemStyle HorizontalAlign="Left" />
</asp:BoundField>
<asp:BoundField DataField="Name" HeaderText="Product Name">
<HeaderStyle HorizontalAlign="Left" Width="150px" />
<ItemStyle HorizontalAlign="Left" />
</asp:BoundField>
<asp:BoundField DataField="ListPrice" HeaderText="Price">
<HeaderStyle HorizontalAlign="Left" Width="50" />
<ItemStyle HorizontalAlign="Right" />
</asp:BoundField>
</Columns>
</asp:gridview>
Thêm 4 nút liên kết đến trang. Tên của chúng tự giải thích. Khi bạn bấm vào nút "First" đi đến trang đầu tiên, nếu bạn bấm vào "Next" phải mất đến trang tiếp theo. Nếu bạn bấm vào liên kết "Previous", nó sẽ đưa bạn đến trang trước và khi bạn click vào "Last".
<table>
<tr>
<td><asp:LinkButton ID="btnFirst" CommandName="Page" RunAt="server" Text="First"
CommandArgument="First" OnCommand="PageChangeEventHandler"/></td>
<td><asp:LinkButton ID="btnPrevious" CommandName="Page" RunAt=server Text="Prev"
CommandArgument="Previous" OnCommand="PageChangeEventHandler"/></td>
<td><asp:LinkButton ID="btnNext" CommandName="Page" RunAt="server" Text="Next"
CommandArgument="Next" OnCommand="PageChangeEventHandler"/></td>
<td><asp:LinkButton ID="btnLast" CommandName="Page" RunAt="server" Text="Last"
CommandArgument="Last" OnCommand="PageChangeEventHandler"/></td>
</tr>
</table>
Để hiển thị người dùng về trang hiện tại.
<i>You are viewing page <%=pageIndex%> of <%=pageCount%> </i>
Source Code:
Chúng ta thiết lập kích thước trang đến 5 trong ví dụ của chúng ta. Thêm 3 biến class để giữ số trang hiện tại, tổng số trang và tổng số hàng.
protected int pageIndex = 1;
protected int pageCount = 0;
protected int rowCount = 0;
private const int CONST_PAGE_SIZE = 5;
Nếu nó là trang lần đầu tiên được nạp, chúng ta index trang mặc định 1 và sẽ tiết kiệm số trang tính trong trạng thái xem. Nếu trang được nạp lại do các sự kiện post back, thì chúng ta nhận được những giá trị từ VIEWSTATE.
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
BindData();
//based on the row count & page size, calculate page count
pageCount = CalcPageCount(rowCount);
ViewState["PageCount"] = pageCount;
RefreshPageButtons();
}
else
{
if (ViewState["PageIndex"] != null)
pageIndex = Convert.ToInt32(ViewState["PageIndex"]);
if (ViewState["PageCount"] != null)
pageCount = Convert.ToInt32(ViewState["PageCount"]);
}
}
private int CalcPageCount(int totalRows)
{
return (int)(totalRows / CONST_PAGE_SIZE);
}
Việc xử lý để tìm ra hồ sơ đã được hiển thị trên các trang web là trong thủ tục lưu trữ. Nó quyết định dựa trên trang hiện tại chúng ta đang ở trên và trên số lượng hồ sơ chúng ta hiển thị trên trang.
CREATE procedure [dbo].[sp_Products_Get]
(
@PageSize int,
@PageIndex int,
@RecordCount int output
)
AS
BEGIN
DECLARE @tblProduct TABLE(
ProductID int not null,
Name varchar(255) ,
ProductNumber varchar(255),
ListPrice decimal
)
DECLARE @index int
SET @ index =@PageSize*(@PageIndex - 1)
INSERT INTO @tblProduct (ProductID, Name,ProductNumber,ListPrice)
SELECT ProductID, Name,ProductNumber,ListPrice FROM tblProduct
SELECT @RecordCount=Count(*) FROM @tblProduct
SET ROWCOUNT @PageSize
SELECT ProductID, Name,ProductNumber,ListPrice FROM @tblProduct WHERE
ProductID > @ index
SET ROWCOUNT 0
END
ADO.NET API được sử dụng để thực hiện thủ tục lưu trữ [sp_Products_Get] và kết nối kết quả vào GridView. Chúng ta cũng nhận được tổng số hàng như một tham số đầu ra, chúng ta lưu trữ nó trong biến class sử dụng tiếp.
private void BindData()
{
DataSet dsProducts = RetrieveProducts();
//Bind the grid view
gvProducts.DataSource = dsProducts;
gvProducts.DataBind();
}
private DataSet RetrieveProducts()
{
if (ViewState["Products"] != null)
return (DataSet)ViewState["Products"];
//fetch the connection string from web.config
string connString =
ConfigurationManager.ConnectionStrings["Sql"].ConnectionString;
DataSet dsProducts = new DataSet();
//Open SQL Connection
using (SqlConnection conn = new SqlConnection(connString))
{
conn.Open();
//Initialize command object
using (SqlCommand cmd = new SqlCommand("sp_Products_Get", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
//add input parameters to the SP
cmd.Parameters.AddWithValue("@PageIndex",pageIndex);
cmd.Parameters.AddWithValue("@PageSize", CONST_PAGE_SIZE);
//add output parameters
cmd.Parameters.Add("@RecordCount", SqlDbType.Int);
cmd.Parameters["@RecordCount"].Direction =
ParameterDirection.Output;
SqlDataAdapter adapter = new SqlDataAdapter(cmd);
//Fill the result set
adapter.Fill(dsProducts);
//get the output value
rowCount = (int)cmd.Parameters["@RecordCount"].Value;
}
}
return dsProducts;
}
Khi bạn nhấn chuột vào bất kỳ nút trang, sự kiện PageChangeEventHandler được bắn ra. Phụ thuộc vào đối số lệnh, chúng ta quyết định nếu người dùng nhấp vào "First", "next", "previous" hoặc "last" và quy trình cho phù hợp. Mỗi trang được làm mới, chúng ta bật/tắt nút trang phụ thuộc vào index trang.
protected void PageChangeEventHandler(object sender, CommandEventArgs e)
{
switch (e.CommandArgument.ToString())
{
case "First":
pageIndex = 1;
break;
case "Prev":
pageIndex = pageIndex - 1;
break;
case "Next":
pageIndex = pageIndex + 1;
break;
case "Last":
pageIndex = pageCount;
break;
}
//set the latest page index back to view state
ViewState["PageIndex"] = pageIndex;
//fetch the latest batch of products
BindData();
//enable/disable page buttons based on current page index
RefreshPageButtons();
}
private void RefreshPageButtons()
{
btnFirst.Enabled = true;
btnPrevious.Enabled = true;
btnNext.Enabled = true;
btnLast.Enabled = true;
//if this is the first page, disable previous page
if (pageIndex == 1)
{
btnPrevious.Enabled = false;
btnFirst.Enabled = false;
//if the page count is more than 1, enable next button
if (pageCount <= 0)
btnNext.Enabled = false;
}
else
{
if (pageIndex == pageCount)
{
btnNext.Enabled = false;
btnLast.Enabled = false;
}
}
}
Câu lệnh SQL:
Tôi đã tạo ra bảng tblProduct và nạp nó với một số dữ liệu thử nghiệm. Nếu bạn muốn sử dụng cùng một bảng, bạn có thể sử dụng kịch bản dưới đây.
CREATE TABLE [dbo].[tblProduct](
[ProductID] [int] IDENTITY(1,1) NOT NULL,
[Name] [varchar](255) NOT NULL,
[ProductNumber] [varchar](255) NOT NULL,
[ListPrice] [numeric](9, 2) NOT NULL,
CONSTRAINT [PK_tblProduct_ProductID] PRIMARY KEY CLUSTERED
(
[ProductID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF,
IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
GO
DECLARE @COUNTER INT, @productname VARCHAR(255),
@productnumber VARCHAR(255), @listprice DECIMAL
SET @COUNTER = 0
SET @productname = 'product name '
SET @productnumber = 'product number '
SET @listprice = 500
WHILE(@COUNTER <= 20)
BEGIN
SET @listprice= @listprice + 100
INSERT INTO [dbo].[tblProduct]
VALUES
(@productname + convert(VARCHAR, @COUNTER)
,@productnumber + convert(VARCHAR, @COUNTER)
,@listprice)
SET @COUNTER = @COUNTER + 1
END
Ảnh chụp màn hình:
Khi bạn chạy ứng dụng, nó sẽ đưa bạn đến trang mặc định.
Bây giờ nếu bạn nhấp vào liên kết "Next", nó sẽ đưa bạn đến trang tiếp theo. Trên trang tiếp theo, bạn sẽ thấy 5 sản phẩm tiếp theo
Khi bạn click vào liên kết "Last", nó sẽ đưa bạn đến trang cuối cùng.
Bây giờ nếu bạn bấm vào liên kết "Previous", nó sẽ đưa bạn đến trang 4.
Nếu bạn bấm vào liên kết "First" nó sẽ đưa bạn đến trang đầu tiên.