2012年7月6日 星期五

ASP.NET MVC 資料分頁 MVCPaging 2.0 應用 Part.2:AJAX 分頁


接續上一篇「ASP.NET MVC 資料分頁 MVCPaging 2.0 應用 Part.1:一般、表單(Form)」,這一篇將會說明如何使用 MvcPaging 的 Ajax.Pager 方式來完成 AJAX 分頁的功能。

 


一開始就先做個基本分頁的方式,先不考慮表單 POST 資料傳送的問題,我們以 MvcPaging.Demo 的 IndexAjax 頁來做為參考範本,參考裡面的作法,

MvcPaging.Demo 的網站專案的下載位置:https://github.com/martijnboland/MvcPaging

image

 

先來看看 MvcPaging.Demo 的 Controller 與 ViewPage 的程式內容,

ViewPage > IndexAjax.cshtml

image

PartialView > _ProductGrid.cshtml

image

而在 PartialView 中的 Html.Pager() 詳細設定設定內容如下:

@Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalItemCount, new AjaxOptions { UpdateTargetId = "gridcontainer"}).Options(o => o.Action("AjaxPage"))

其中 AjaxOptions 的設定是使用了 System.Web.Mvc.Ajax.AjaxOptions,所以這邊會需要指定一個要更換內容的容器 ID,然後再後面的 Options() 中要去指定在 Controller 中處理分頁內容的 Action 方法。

MSDN:System.Web.Mvc.Ajax 命名空間

MSDN:AjaxOptions 類別

因為是使用了 System.Web.Mvc.Ajax,所以記得要在 ViewPage 上加入 jquery.unobtrusive-ajax.js 檔案的引用,像 MvcPaging.Demo 則是在 _Layout.cshtml 中加入「jquery.unobtrusive-ajax.min.js」的使用,

image

記得一定要加入,不然是 MvcPaging 的 Html.Pager() 是無法有 Ajax 的效果。

另外 ASP.NET MVC 使用 AjaxHelper 上需要注意一些設定的地方,可以參考下面的這篇 KKBruce 所寫的文章,

KKBruce:ASP.NET MVC 2與MVC 3使用AJAXHELPER引用JAVASCRIPT檔不同

 

Controller > IndexAjax, AjaxPage

image

MvcPaging.Demo 的 Ajax 分頁做法就是把要分頁處理的 Pager 與表格內容給抽出來放在 PartialView 檔案裡,點選分頁連結後將分頁碼送回到後端 Controller 的 AjaxPage,AjaxPage 取出分頁資料後,將分頁資料使用 PartialView 送回到前端,前端接收到後端所傳回來的分頁內容後,再去替換掉 ID 為「gridcontainer」的內容,如此就完成 AJAX 分頁的功能。

 


 

實作

我們看完 MvcPaging.Demo 的範例之後,再回來看我們要用來做 AJAX 分頁的網頁,資料呈現的頁面是沿用「ASP.NET MVC 資料分頁 MVCPaging 2.0 應用 Part.1:一般、表單(Form)」的 DefaultPage 頁,

image

點選 Pager 的分頁連結後所需要更換的內容是下圖紅線所框起來的部分,這個紅線所框起來的部分就要抽出來另外做為 PartialView 內容,而其他的內容則還是留在原來的主頁面中,

image

先處理表單內容的前端事件處理,這邊要做 AJAX 處理,所以原本表單的 submit POST 就需要做另外的處理,改使用 jQuery 的 AJAX 來處理表單資料 POST 的動作,因為是要修改為 AJAX,當表單送出並取得資料後,有時候使用者去變動表單中的下拉選單所選擇的值,然後又去點選分頁連結,而造成表單值與顯示結果不一致,所以當表單送出之後就會將下拉選單做 disable 的處理;

另外連帶要做修改的就是 reset 的部份,因為 submit 表單資料後會 disable 下拉選單,所以 reset 的事件處理就是解除下拉選單的 disable 以及將下拉選單的選取狀態設為預設值,另外還要做的就是清空 gridcontainer 的內容,以下的這段 jQuery 程式內容是放在 DefaultPageAjax.cshtml 當中,

@if (false){ <script src="../../Scripts/jquery-1.7.2.min.js" type="text/javascript"></script> }
<script type="text/javascript">
<!--
    $(document).ready(function () {
        $('#ButtonSubmit').click(function () { ButtonSubmitEventHandler(); });
        $('#ButtonReset').click(function () { ButtonResetEventHandler(); });
    });
    function ButtonSubmitEventHandler() {
        var cityValue = $('#city option:selected').val();
        var columnValue = $('#sortColumnName option:selected').val();
        var sortValue = $('#sort option:selected').val();
        $.ajax({
            url: '@Url.Action("DefaultPageAjaxPartial", "Home")',
            data: { city: cityValue, sortColumnName: columnValue, sort: sortValue },
            type: 'post',
            async: false,
            cache: false,
            dataType: 'html',
            success: function (data) {
                $('#gridcontainer').html(data);
                $('#city').attr('disabled', true);
                $('#sortColumnName').attr('disabled', true);
                $('#sort').attr('disabled', true);
            }
        });
    }
    function ButtonResetEventHandler() {
        $('#city option:eq(0)').attr('selected', true);
        $('#sortColumnName option:eq(0)').attr('selected', true);
        $('#sort option:eq(0)').attr('selected', true)
        $('#city').removeAttr('disabled');
        $('#sortColumnName').removeAttr('disabled');
        $('#sort').removeAttr('disabled');
        $('#gridcontainer').empty();
    }
-->
</script>

 

DefaultPageAjax.cshtml

因為沒有在 _Layout.cshtml 去加入「jquery.unobtrusive-ajax.min.js」,所以就直接在 DefaultPageAjax.cshtml 中加入,

@model IPagedList<MvcMSSQL.Models.Customer>
@{
    ViewBag.Title = "DefaultPageAjax";
    Layout = "~/Views/Shared/_Layout.cshtml";
}
<script type="text/javascript" src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")"></script>
<h2>DefaultPageAjax</h2>
<fieldset>
    <br />
    City:@Html.Raw(ViewData["CityDDL"].ToString()) 
    Sort ColumnName:@Html.Raw(ViewData["ColumnDDL"].ToString())
    Sort Type:@Html.Raw(ViewData["SortDDL"].ToString())
    <input type="button" value="submit" id="ButtonSubmit" />
    <input type="button" value="Reset" id="ButtonReset" />
</fieldset>
<div id="gridcontainer">
    @Html.Partial("DefaultPageAjaxPartial", Model)
</div>

 

接下來再看 PartialView「DefaultPageAjaxPartial.cshtml」的內容,在 PartialView「DefaultPageAjaxPartial.cshtml」這邊要特別注意的就是 Html.Pager() 的設定,

<div class="pager">
    @Html.Pager(Model.PageSize, Model.PageNumber, Model.TotalItemCount, new AjaxOptions { UpdateTargetId = "gridcontainer" }).Options(o => o
        .Action("DefaultPageAjaxPartial")
        .AddRouteValue("city", ViewBag.City)
        .AddRouteValue("sortColumnName", ViewBag.SortColumnName)
        .AddRouteValue("sort", ViewBag.Sort))
    Displaying @Model.ItemStart - @Model.ItemEnd of @Model.TotalItemCount item(s)
</div>

要去增加 AjaxOptions 的內容,並且指定 AJAX 要做更換的容器 ID,然後在 Options 中加入後端 PartialView 的處理 Action 方法名稱,還有增加 RouteValue 設定,增加 RouteValue 設定值,這樣在做 AJAX 分頁時一樣可以維持表單裡下拉選單的選取條件。

最後貼上 Controller 裡的 Action() 程式內容:

private const int DefaultPageSize = 5;
private IList<Customer> allCustomers = new List<Customer>();
public ActionResult DefaultPageAjax()
{
    int currentPageIndex = 0;
    this.PrepareDropDownLists(this.FilterCity, this.SortColumnName, this.SortType);
    ViewBag.City = this.FilterCity;
    ViewBag.SortColumnName = this.SortColumnName;
    ViewBag.Sort = this.SortType;
    ViewData.Model = this.allCustomers.ToPagedList(currentPageIndex, DefaultPageSize);
    return View();
}
public ActionResult DefaultPageAjaxPartial(int? page,
    string city = "all",
    string sortColumnName = "CustomerID",
    string sort = "asc")
{
    int currentPageIndex = page.HasValue ? page.Value - 1 : 0;
    this.FilterCity = city;
    this.SortColumnName = sortColumnName;
    this.SortType = sort;
    ViewBag.City = city;
    ViewBag.SortColumnName = sortColumnName;
    ViewBag.Sort = sort;
    using (NorthwindEntities db = new NorthwindEntities())
    {
        var query = db.Customers.Select(x => x);
        if (!city.Equals("all"))
        {
            query = query.Where("City == @0", city ?? "London");
        }
        query = query.OrderBy(string.Format("{0} {1}", sortColumnName, sort));
        ViewData.Model = query.ToPagedList(currentPageIndex, DefaultPageSize);
        return PartialView("DefaultPageAjaxPartial");
    }
}

 

執行結果:

初始頁面

image

按下 submit 後,表單的下拉選單都 disable 並於下方顯示 Pager 與資料內容

image

顯示其他分頁

image

點選 reset 以清除分頁內容

image

調整表單的下拉選單選取值後送出,

image

顯示其他分頁

image

 

這邊觀察有關資料傳送的內容,當點選一個分頁連結後,傳送到後端的資料內容如下:

image

 

而後端傳回到前端的內容如下:

可以看到這個 PartialView 的內容是 Pager 與 Table 的原始碼,

image

HTML 內容

image

 

操作影片

 

下回再來說明如何使用 jQuery 來達成 AJAX 分頁的功能……

 

以上

沒有留言:

張貼留言

提醒

千萬不要使用 Google Talk (Hangouts) 或 Facebook 及時通訊與我聯繫、提問,因為會掉訊息甚至我是過了好幾天之後才發現到你曾經傳給我訊息過,請多多使用「詢問與建議」(在左邊,就在左邊),另外比較深入的問題討論,或是有牽涉到你實作程式碼的內容,不適合在留言板裡留言討論,請務必使用「詢問與建議」功能(可以夾帶檔案),謝謝。