FineUIMvc随笔(6)对比WebForms和MVC中表格的数据库分页

声明: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 

posted @ 2017-03-14 10:33 三生石上(FineUI控件) 阅读(...) 评论(...) 编辑 收藏