摘要:ASP.NET MVC 分頁實作
前言
在.Net Web Form時代,我們常使用GridView控制項來顯示列表清單,也可以很容易做到分頁效果。雖然後來我都是使用DataRepeater來取代,但有時遇到資料筆數不多或是自己在寫測試網頁時,為了快速產生列表偶爾還是會使用到它;不得不說GridView用起來實在很方便,但相對的也產生龎大的ViewState,拖慢了網頁的執行速度。到了.Net MVC架構,沒有元件可以使用,我們就需要手工打造分頁功能,以下就以我常用的寫法做說明。
分頁實作
1.建立Sql Procedure
Create PROCEDURE [dbo].[PaingTest]
(
@PageIndex int,
@PageRows int
)
AS
with #tmp1 as
(
SELECT ROW_NUMBER() OVER (ORDER BY userid) AS ROW, userid, updatedate FROM member WITH(NOLOCK)
)
select ROW, userid, updatedate from #tmp1 WITH(NOLOCK)
WHERE #tmp1.ROW >= (@PageRows * @PageIndex) + 1
AND #tmp1.ROW <= (@PageRows * @PageIndex) + @PageRows
order by row
*參數說明:
@PageIndex - Page索引值
@PageRows int -Page顯示的資料數
2..Net MVC加入Sql Procedure
(1) 開啟建立好的Entity Framework檔案(*.edmx), 按右鍵,選擇Update Model from Database....。
(2) 選擇要加入的分頁Stored Procedures。
(3) 接著在右邊Model Browser就可以看到Stored Procedure已加入。
再點右鍵,選擇「Add Function Import...」
(4) 建立Function
4.1 命名Function - Paging Test
4.2 點選Get Column Information
4.3 再點選Create New Complex Type,即會在Complex出現回傳的資料集-Paging Test_Result
最後選擇ok後就完成Store Procedure的匯入。
5. 建立分頁Repository
(1) 建立Interface - IPaging
建立GetErrorLog功能,以取得資料清單
建立GetData功能,來取得
public interface IPaging
{
IEnumerable<> GetUserList(int PageInex, int PageRow);
string GetPageData(Controller controller, int PageInex, int PageSize);
string GetPageData(int PageInex, int PageSize);
}
(2) 實作IPaging類別
public class Paging : IPaging
{
public IEnumerable<<PagingTest_Result>> GetUserList(int PageInex, int PageRow)
{
DB19113Entities db = new DB19113Entities();
return db.PagingTest(PageInex, PageRow).ToList();
}
public string GetPageData(int PageInex, int PageSize)
{
return GetPageData(null, PageInex, PageSize);
}
public string GetPageData(Controller controller, int PageInex, int PageSize)
{
DB19113Entities db = new DB19113Entities();
int rs = db.Error_log.Count();
int lastpage = 0;
if (rs % PageSize == 0)
{
int flag = (rs / PageSize) - 1;
lastpage = (flag >> 0) ? flag : 1;
}
else
lastpage = rs / PageSize;
string ctl = controller.RouteData.Values["controller"].ToString();
string action = controller.RouteData.Values["action"].ToString();
string path = @"/" + ctl + "/" + action + "/";
System.Text.StringBuilder sb = new System.Text.StringBuilder();
sb.Append("<<a href='" + path + "0'>>第1頁|<<<</a>> ");
int findex = 0;
int lindex = lastpage;
findex = ((PageInex + 1) - 5 <<= 1) ? 1 : (PageInex + 1) - 5;
lindex = (findex + 10 >>= lastpage) ? lastpage : findex + 10;
if (lindex - findex <<= 10)
{
findex = ((lindex - 10) <<= 1) ? 1 : (lindex - 10);
}
for (int i = findex; i <<= lindex; i++)
{
if (i == findex)
{
if ((((PageInex + 1) <<= 1) ? 1 : (PageInex + 1)) != 1)
sb.Append("<<a href='" + path + (findex - 1) + "'>>...<</a>> ");
else
sb.Append(i.ToString() + " ");
}
else if (i == lindex)
{
if ((((PageInex + 1) >> lastpage) ? lastpage : (PageInex 1)) != lastpage)
sb.Append("<<a href='" + path + (lindex + 1) + "'>>...<</a>> ");
else
sb.Append(i.ToString() + " ");
}
else if ((PageInex + 1) == i)
sb.Append(i.ToString() + " ");
else
sb.Append("<<a href='" + path + (i - 1) + "'>>" + i.ToString() + "<</a>> ");
}
sb.Append("<<a href='" + path + lastpage + "'>>第後頁>>|<</a>> ");
return sb.ToString();
}
}
(3) 建立Controller
public class PagingController : Controller
{
private IPaging paing;
public PagingController()
{
paing = new Paging();
}
public ActionResult Index(int page = 0)
{
ViewBag.Page = paing.GetPageData(this,page, 10);
return View(paing.GetUserList(page, 10).ToList());
}
}
(4) 建立View
建立強型別,選擇Stored Procedure的model 類別,而template使用List來呈現。
建立View後,使用ViewBag來輸出分頁結果,Html語法以@MvcHtmlString來輸出,如下:
//@Html.Raw(@ViewBag.Page)
@MvcHtmlString.Create(@ViewBag.Page)
(5) 最後顯示結果如下:
3. 更新Stored Procedure
當我們更新Stored procedure時,有時select的欄位有異動時,MVC的model也要做更新,其步驟如下:
(1) 開啟Travel.edmx,並切換到Model Browser。
(2) 展開Complex Types,可直接更接命名新的屬性,或是先將其刪除。
(3) 之後,展開EntityContainer的Function Imports,即可看到當初新增的function名稱,可以選擇Edit重新編輯 ,並可取得新的Complex Type。
* 補充:使用Linq語法處理分頁
感謝kkk大大的部充,如不使用Stored procedure的分式,可以改以Linq語法做分頁,用到的查詢Method有OrderyBy、Skip及Take,
也可以達到分頁的效果,如下所示:
public IEnumerable<<users>> GetUserList(int PageInex, int PageRow)
{
DB19113Entities db = new DB19113Entities();
return db.users.OrderBy(m => m.id).Skip((PageInex) * PageRow).Take(PageRow).ToList();
}