FineUIMvc隨筆(6)對比WebForms和MVC中表格的資料庫分頁

三生石上(FineUI控制元件)發表於2017-03-14

宣告:FineUIMvc(基礎版)是免費軟體,本系列文章適用於基礎版。

透過對比WebForms和MVC中表格資料庫分頁程式碼的不同,可以對 MVC 中的資料流轉有更加深入的瞭解。

WebForms 中表格的資料庫分頁

WebForms中的程式碼會比較直觀,我們從具體是示例入手:

http://fineui.com/demo/#/demo/grid/grid_paging_database.aspx

前臺標籤定義,簡單起見省略了部分列定義:

<f:Grid ID="Grid1" Title="表格" EnableCollapse="true" Width="800px" PageSize="5" ShowBorder="true" ShowHeader="true"
    AllowPaging="true" runat="server" EnableCheckBoxSelect="True" ShowPagingMessage="false"
    DataKeyNames="Id,Name" IsDatabasePaging="true" OnPageIndexChange="Grid1_PageIndexChange">
    <Columns>
        <f:RowNumberField />
        <f:BoundField Width="100px" DataField="Name" DataFormatString="{0}" HeaderText="姓名" />
        .....
    </Columns>
</f:Grid>

為了啟用資料庫分頁,我們需要定義如下屬性:

1. AllowPaging=true:啟用分頁

2. IsDatabasePaging=true:啟用資料庫分頁

3. PageSize=5:每頁記錄數

4. OnPageIndexChange=Grid1_PageIndexChange:分頁切換事件,需要回發到後臺重新繫結表格資料

 

後臺的初始化程式碼:

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        BindGrid();
    }
}

private void BindGrid()
{
    // 1.設定總項數(特別注意:資料庫分頁一定要設定總記錄數RecordCount)
    Grid1.RecordCount = GetTotalCount();

    // 2.獲取當前分頁資料
    DataTable table = GetPagedDataTable(Grid1.PageIndex, Grid1.PageSize);

    // 3.繫結到Grid
    Grid1.DataSource = table;
    Grid1.DataBind();
}

資料繫結時執行了三個操作:

1. 設定表格總記錄數,在資料庫分頁時這個是必須要的

2. 獲取當前分頁資料,傳入當前頁序號(預設為PageIndex=0)以及每頁顯示記錄數

3. 將資料繫結到表格

 

後臺的分頁事件處理函式:

protected void Grid1_PageIndexChange(object sender, GridPageEventArgs e)
{
    BindGrid();
}

分頁回發事件中,表格會自動記錄當前頁序號,所以這裡只需要簡單的呼叫 BindGrid 函式即可!程式碼簡單,一氣呵成!

 

在 MVC 中就沒那麼容易的了。

 

MVC 中表格的資料庫分頁

我們來看具體的示例:http://fineui.com/demo_mvc#/demo_mvc/GridPaging/Database

 

首先看下前臺 View 的定義:

@(F.Grid()
    .EnableCheckBoxSelect(true)
    .Width(850)
    .ShowHeader(true)
    .ShowBorder(true)
    .EnableCollapse(true)
    .Title("表格")
    .ID("Grid1")
    .DataIDField("Id")
    .DataTextField("Name")
    .AllowPaging(true)
    .PageSize(5)
    .IsDatabasePaging(true)
    .OnPageIndexChanged(Url.Action("Grid1_PageIndexChanged"), "Grid1")
    .Columns(
        F.RowNumberField(),
        F.RenderField()
            .HeaderText("姓名")
            .DataField("Name")
            .Width(80),
        ......
    )
    .RecordCount(ViewBag.Grid1RecordCount)
    .DataSource(ViewBag.Grid1DataSource)
)

和 WebForms 中的類似,我們同樣需要設定一些屬性來啟用資料庫分頁:

1. AllowPaging(true):啟用分頁

2. IsDatabasePaging(true):啟用資料庫分頁

3. PageSize(5):每頁記錄數

4. OnPageIndexChanged(Url.Action("Grid1_PageIndexChanged"), "Grid1"):分頁切換事件,需要回發到後臺重新繫結表格資料

注意 OnPageIndexChanged 事件處理函式的定義,它比 WebForms 中多了個引數 Grid1,在前面文章中我們知道這個引數會把表格的相關分頁排序等資訊一起回發到後臺。

為什麼WebForms不需要這些資訊呢?

因為 WebForms 透過 ViewState 等內部機制來維持 HTTP 請求之間控制元件的狀態,從而可以方便的在後臺使用 Grid1.PageIndex 等屬性。

 

除了上面的四個屬性,你可能還注意到如下兩個設定:

5. RecordCount(ViewBag.Grid1RecordCount)
6. DataSource(ViewBag.Grid1DataSource)

這兩個是透過 ViewBag 從控制器傳入的引數,分別對應於表格總記錄數和當前分頁資料來源。對比下 WebForms 中實現,我們可以清楚的意識到:

1. WebForms中頁面初始化時,後臺程式碼能夠直接訪問到頁面(.aspx)上定義的控制元件,所以可以直接在後臺程式碼中對控制元件賦值。

2. MVC中頁面初始化時,後臺程式碼不能訪問到檢視(.cshtml)上定義的控制元件,所以必須在控制器方法中準備好資料,然後傳入檢視中。

 

看下頁面初始化時,MVC如何準備表格分頁資料,並儲存到 ViewBag 中:

// GET: GridPaging/Database
public ActionResult Index()
{
    LoadData();

    return View();
}

private void LoadData()
{
    var recordCount = DataSourceUtil.GetTotalCount();

    // 1.設定總項數(特別注意:資料庫分頁初始化時,一定要設定總記錄數RecordCount)
    ViewBag.Grid1RecordCount = recordCount;

    // 2.獲取當前分頁資料
    ViewBag.Grid1DataSource = DataSourceUtil.GetPagedDataTable(pageIndex: 0, pageSize: 5, recordCount: recordCount);
}

 

正因為如此,在MVC中,頁面初始化和之後的事件處理函式(回發)不能共用 BindGrid 類似的函式。

因此,在分頁切換事件處理函式中(換成MVC的術語:客戶端的分頁事件對應的後臺控制器方法),我們需要透過 UIHelper 幫助來更新表格資料:

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Grid1_PageIndexChanged(JArray Grid1_fields, int Grid1_pageIndex)
{
    var grid1 = UIHelper.Grid("Grid1");

    var recordCount = DataSourceUtil.GetTotalCount();

    // 1.設定總項數(資料庫分頁回發時,如果總記錄數不變,可以不設定RecordCount)
    grid1.RecordCount(recordCount);

    // 2.獲取當前分頁資料
    var dataSource = DataSourceUtil.GetPagedDataTable(pageIndex: Grid1_pageIndex, pageSize: 5, recordCount: recordCount);
    grid1.DataSource(dataSource, Grid1_fields);

    return UIHelper.Result();
}

注意,控制器方法的兩個引數名稱是約定好的,如果前臺透過控制元件ID的方式來傳入自定義回發引數時:

OnPageIndexChanged(Url.Action("Grid1_PageIndexChanged"), "Grid1")

後臺接受請求的引數名約定為:

1. 表格控制元件ID_pageIndex:表格當前分頁序號

2. 表格控制元件ID_fields:表格用到了哪些表格欄位(如果不是表格,是IEnumrable<Class>物件,則對應於類屬性列表),這個值在資料繫結時需要用到。

 

為什麼需要 Grid1_fields 引數?

很多網友會有這個疑問,其實理解起來也很簡單。因為表格可能存在很多欄位,假設有 100 個,可能只有其中的 10 個欄位表格用到了。那麼資料繫結時只返回這 10 個欄位的資料。

假設資料繫結時沒有傳入這個引數,也是可以執行的,只不過會返回很多冗餘資料,也可能會造成關鍵資料洩密(比如密碼等)。

 

最後,我們看下 MVC 中,分頁回發的請求正文:

 

響應正文:

F.ui.Grid1.setRecordCount(22);
F.ui.Grid1.loadData([
    [106, "張博", 1, 2003, true, "財務管理", 3, "2017-01-13T07:22:51Z"],
    [107, "楊倩倩", 0, 2000, false, "材料物理與化學", 4, "2017-01-23T07:22:51Z"],
    [108, "董超", 1, 2004, false, "生物醫學工程", 4, "2017-02-02T07:22:51Z"],
    [109, "張娟娟", 0, 2003, true, "材料物理與化學", 5, "2017-02-12T07:22:51Z"],
    [110, "葉鵬", 1, 2006, false, "電子商務", 5, "2017-02-22T07:22:51Z"]
]);
F.ui.Grid1.clearSelection();

 

小結

學習 FineUIMvc 中表格的資料庫分頁程式碼,關鍵是要理解 WebForms 和 MVC 的不同工作方式。

WebForms中頁面初始化時,後臺程式碼可以直接訪問頁面控制元件,所以能直接在後臺程式碼中對控制元件進行資料繫結。MVC中頁面初始化時,控制器方法中不能訪問檢視中定義的控制元件,需要準備資料透過ViewBag或者模型物件傳入到檢視中。

WebForms中頁面回發時,後臺程式碼可以知道控制元件的所有屬性。MVC中頁面回發時,後臺程式碼需要的任何引數都要由前臺透過JavaScript程式碼顯式的傳入(FineUIMvc提供了控制元件ID作為引數的簡單傳值方法)。

 

《FineUIMvc隨筆》目錄:http://www.cnblogs.com/sanshi/p/6473592.html 

相關文章