[ASP.net MVC 4] 自己打造分頁Pager範例程式碼 (下拉選單版,表單Post方式)

[ASP.net MVC 4] 自己打造分頁Pager範例程式碼 (下拉選單版,表單Post方式)

前言

把所有頁數都塞進下拉選單,這樣的做法寫的程式碼少,也比較簡單

因為之前有PO過Ajax查詢方式:[ASP.net MVC 4] 自己打造分頁Pager範例程式碼 (數字版,Ajax)

所以這篇就改用表單Post來寫寫看

說明都在程式碼註解裡

 

 

實作

Models資料夾加入


using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace MvcApplicationPager.Models
{
    public class ProductViewModel
    {
        /// <summary>
        /// 編號
        /// </summary>
        public int No { get; set; }
        /// <summary>
        /// 名稱
        /// </summary>
        public string ProductName { get; set; }
        /// <summary>
        /// 是否上下架
        /// </summary>
        public bool IsOpen { get; set; }

         
    }
}

Demo用,在Global.asax.cs 塞假資料


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Web.Mvc;
using System.Web.Routing;

namespace MvcApplicationPager
{
    // Note: For instructions on enabling IIS6 or IIS7 classic mode, 
    // visit http://go.microsoft.com/?LinkId=9394801
    public class MvcApplication : System.Web.HttpApplication
    {
        //假裝這是DB撈出來的資料
        public static List<ProductViewModel> dbList = new List<ProductViewModel>();
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            
            #region 塞假資料
            Random rand = new Random(Guid.NewGuid().GetHashCode());
            for (int i = 1; i <= 104; i++)
            {
                bool IsOpen = true;//Default
                int number = rand.Next(1, 3);//1~2
                if (number == 2)
                {
                    IsOpen = false;
                }
                dbList.Add(new ProductViewModel()
                {

                    No = i,
                    ProductName = Guid.NewGuid().ToString().Substring(0, 5).ToUpper(),
                    IsOpen = IsOpen
                });
            }
            #endregion
           
            WebApiConfig.Register(GlobalConfiguration.Configuration);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
        }
    }
}

 

控制器

HomeController.cs


using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

//剛剛宣告的
using MvcApplicationPager.Models;
using System.Text;
 
namespace MvcApplicationPager.Controllers
{
    public class HomeController : Controller
    {
        //準備畫面上下拉選單資料
        private void initViewData(string selectValue)
        {
            //上下架的下拉選單的資料清單
            ViewData["IsOpenItems"] = new List<SelectListItem>() 
            { 
              new SelectListItem(){ Text="請選擇",Value="-1",Selected=(selectValue=="-1")},
              new SelectListItem(){ Text="上架",Value="true" ,Selected=(selectValue=="true")},
              new SelectListItem(){ Text="下架",Value="false" ,Selected=(selectValue=="false")},
            };
        }
        [HttpGet]
        public ActionResult Index()
        {
            this.initViewData("-1");

            IEnumerable<ProductViewModel> result = this.QueryData(10, 0, new FormCollection());

            return View(result);
        }



        /// <summary>
        /// 查詢資料
        /// </summary>
        /// <returns></returns>
        public IEnumerable<ProductViewModel> QueryData(int iPageSize, int iCurrentPageIndex, FormCollection form)
        {
            var result = from r in MvcApplication.dbList
                         select r;
            if (!string.IsNullOrEmpty(form["sProductName"]))
            {//有輸入名稱
                result = from r in result
                         where r.ProductName.Contains(form["sProductName"])
                         select r;
            }
            //有輸入上下架
            if (form["sIsOpen"] != null && form["sIsOpen"] != "-1")
            {

                result = from r in result
                         where r.IsOpen == Convert.ToBoolean(form["sIsOpen"])
                         select r;

            }
            //顯示TempData["pager"]
            TempData["pager"] = this.pageString(result,iPageSize,iCurrentPageIndex);
            

            //抓DB少量的資料
            result = result.Skip(iCurrentPageIndex * iPageSize).Take(iPageSize);
 
            return result;
        }
        /// <summary>
        /// 產生pager字串(這個請再自行抽到其他Utility之類的類別裡)
        /// </summary>
        /// <param name="result">集合物件</param>
        /// <param name="iPageSize">每頁顯示幾筆</param>
        /// <param name="iCurrentPageIndex">目前的索引頁</param>
        /// <returns></returns>
        public string pageString(IEnumerable<object> result,int iPageSize,int iCurrentPageIndex)
        {
            #region Pager處理(文章重點在這!)
            //總筆數
            int iRowTotal = result.Count();
            //總頁數
            int iPageTotal = (iRowTotal / iPageSize);
            if (iRowTotal % iPageSize > 0)
            {
                iPageTotal++;
            }
            //目前頁數
            int iCurrentPage = iCurrentPageIndex + 1;
            //防呆 
            if (iCurrentPage > iPageTotal)
            {
                iCurrentPage = iPageTotal;
                iCurrentPageIndex = iCurrentPage - 1;
            }
            if (iCurrentPage < 0)
            {
                iCurrentPage = 1;
                iCurrentPageIndex = 0;
            }
             

            //要回傳的字串
            StringBuilder sb = new StringBuilder();
            //第二頁以後才有上一頁
            string strPreJS = ((iCurrentPage > 1) ? "javascript:search('" + (iCurrentPage - 1) + "');" : "#");
            //顯示總筆數
            sb.Append("合計:" + iRowTotal+"筆");
            //顯示上一頁
            sb.Append("<a href=\"" + strPreJS + "\">← Prev</a>");
            //顯示第一頁
            sb.Append("<a href=\"javascript:search(1);\">First</a>");

            //處理下拉選單
            sb.Append("目前第");
            sb.Append("<select name='selectCurrentPage' onchange=\"search(this.value);\">"); 
            //把所有頁數塞進下拉選單(從1算起)
            for (int i = 1; i <= iPageTotal; i++)
            {
                bool bSelected = (i==iCurrentPage);//表單Post後,下拉選單要停在剛剛選擇的值
                sb.Append("<option value='" + i + "' " + (bSelected ? "selected" : "") + ">" + i + "</option>");
            }
            sb.Append("</select>");
            sb.Append("頁");
            
            //目前頁小於最後一頁,就有下一頁按鈕
            string strNextJS = (iCurrentPage < iPageTotal ? "javascript:search('" + (iCurrentPage + 1) + "');" : "#");
            //顯示最後一頁
            sb.Append("<a href=\"javascript:search(" + iPageTotal + ");\">Last</a>");
            //顯示下一頁
            sb.Append("<a href=\"" + strNextJS + "\">Next → </a>");
           

            
            #endregion

            return sb.ToString();
        
        }

        /// <summary>
        /// 表單Post查詢資料
        /// </summary>
        /// <param name="iPageSize"></param>
        /// <param name="iCurrentPageIndex"></param>
        /// <returns></returns>
        [HttpPost]
        public ActionResult Index(FormCollection form)
        {
           
          
            //這裡的int iPageSize, int iCurrentPageIndex參數,前端使用者可能會用F12開發者工具亂改成字串
            //怎麼防禦就請自由料理了...
            int iPageSize = Convert.ToInt32(form["selectPageSize"]);
            int iCurrentPageIndex = (Convert.ToInt32(form["selectCurrentPage"]) - 1);
            IEnumerable<ProductViewModel> result = this.QueryData(iPageSize, iCurrentPageIndex, form);

            //下拉選單剛剛選擇的值要keep住
            ViewData["iPageSize"] = iPageSize;
            this.initViewData(form["sIsOpen"]);
            return View(result);
        }

    }
}

View的Index.cshtml



<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width" />
    <title>Demo下拉選單分頁(Post版)</title>
    <script type="text/javascript" src="@Url.Content("~/Scripts/jquery-2.0.0.min.js")"></script>
    @*複製範例時候,這個css可以刪除*@
    <style type="text/css">
        /*讓pager各超連結間有空隔*/
        #divPager a {
            margin: 2px;
        }
    </style>
    <script type="text/javascript">
        //表單Post查詢
        function search(pageNumber) {
            //記下目前頁數
            // $("select[name='selectCurrentPage']")來自Controller端組成的分頁字串
            $("select[name='selectCurrentPage']").val(pageNumber);
            //提交表單
            $("form[name='myForm']").submit();    
        }
    </script>
</head>
<body>

    @using (Html.BeginForm("Index", "Home", FormMethod.Post, new { name = "myForm" }))
    {
        
        <div>
            名稱:@Html.TextBox("sProductName")<br />
            上下架:@Html.DropDownList("sIsOpen", (IEnumerable<SelectListItem>)ViewData["IsOpenItems"])<br />
            每頁顯示幾筆:@Html.DropDownList("selectPageSize", new List<SelectListItem>() { 
           new SelectListItem(){ Text="10",Value="10",Selected=(Convert.ToInt32(ViewData["iPageSize"]) ==10)},
           new SelectListItem(){ Text="30",Value="30",Selected=(Convert.ToInt32(ViewData["iPageSize"]) ==30)},
           new SelectListItem(){ Text="50",Value="50",Selected=(Convert.ToInt32(ViewData["iPageSize"]) ==50)},
          }, new { onchange = "search(1);" })
            @*按下搜尋後,到搜尋結果第1頁*@
            <input type="button" value="搜尋"  onclick="search(1);"  /><br />

        </div>
         
        <table cellspacing="0" cellpadding="0" border="1">
            <thead>
                <tr>
                    <th>編號</th>
                    <th>名稱</th>
                    <th>上下架</th>
                </tr>
            </thead>
            <tbody>
                @foreach (var item in Model)
                {
                    <tr>
                        <td>@item.No</td>
                        <td>@item.ProductName</td>
                        <td>@item.IsOpen</td>
                    </tr>
                }
            </tbody>
        </table>
        <br />
        @*分頁*@
        <div id="divPager">
            @Html.Raw(TempData["pager"])
        </div>
           
        

    }

</body>
</html>

執行畫面

image

結語

本文範例程式碼下載,放到MSDN期滿