ASP.NET MVC 分頁實作

  • 3846
  • 0
  • 2013-11-22

摘要: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();
    }