|
WebGrid 给我们开发人员提供了很好的分页和排序功能,优点很明显。但看完下面的例子后会发现一个问题:不管获取每一页都会去取出所有的数据,假如说其中有100W条数据,在用foreach去循环的话,就会造成crash,所以需要我们更好地派生WebGrid类。
创建派生 WebGrid其中用...代替的大家可以通过F12到WebGrid class中查看具体参数,比较多,所以这边就用...代替了- public class WebGrid<T> : WebGrid
- {
- public WebGrid(
- IEnumerable<T> source = null,
- ...
- parameter list omitted for brevity)
- : base(
- source.SafeCast<object>(),
- ...
- parameter list omitted for brevity)
- { }
- public WebGridColumn Column(
- string columnName = null,
- string header = null,
- Func<T, object> format = null,
- string style = null,
- bool canSort = true)
- {
- Func<dynamic, object> wrappedFormat = null;
- if (format != null)
- {
- wrappedFormat = o => format((T)o.Value);
- }
- WebGridColumn column = base.Column(
- columnName, header,
- wrappedFormat, style, canSort);
- return column;
- }
- public WebGrid<T> Bind(
- IEnumerable<T> source,
- IEnumerable<string> columnNames = null,
- bool autoSortAndPage = true,
- int rowCount = -1)
- {
- base.Bind(
- source.SafeCast<object>(),
- columnNames,
- autoSortAndPage,
- rowCount);
- return this;
- }
- }
-
- public static class WebGridExtensions
- {
- public static WebGrid<T> Grid<T>(
- this HtmlHelper htmlHelper,
- ...
- parameter list omitted for brevity)
- {
- return new WebGrid<T>(
- source,
- ...
- parameter list omitted for brevity);
- }
- }
复制代码 这样做有什么好处呢? 通过实现这个新的 WebGrid<T>,我添加了一个新的 Column 方法,该方法以 Func<T, object> 作为 format 参数,这意味着在调用扩展方法时不必再进行转换。
通过这种 Grid 扩展方法,您能够利用编译器针对范型参数的类型推断功能。 因此,本例中我们只需要编写 Html.Grid(Model),而不必编写新的 WebGrid<Object>(Model)。 无论采用哪种方式,返回的类型都是 WebGrid<Object>。例如:- public class PagedObjsModel
- {
- /// <summary>
- /// Model
- /// </summary>
- public IEnumerable<object> ModelValue { get; set; }
- /// <summary>
- /// 每页个数
- /// </summary>
- public int PageSize { get; set; }
- /// <summary>
- /// 页码
- /// </summary>
- public int PageNumber { get; set; }
- /// <summary>
- /// 总数
- /// </summary>
- public int TotalRows { get; set; }
- }
复制代码 实现 WebGrid 服务器端分页的第一步是限制从数据源检索的数据量。 为此,需要知道请求的是哪一页数据,以便检索正确的数据页。 WebGrid 在呈现分页链接时,会重复使用页面的 URL,并在页码中附加一个查询字符串参数,例如 http://localhost:27617/Product/DefaultPagingAndSorting?page=3(该查询字符串参数的名称可通过帮助程序参数进行配置,这在支持同一页面中多个网格的分页时非常有用)。 也就是说,您可以在自己的操作方法中采用一个名为 page 的参数,然后使用查询字符串值填充该参数。
如果只是通过修改现有代码向 WebGrid 传递单页数据,则 WebGrid 只会看到单页数据。 由于它不知道还有别的页面,因而不再呈现分页器控件。 幸运的是,WebGrid 还有一种名为 Bind 的方法,可用来指定数据。 Bind 不仅能够接受数据,而且有一个表示总行数的参数,从而据此计算页数。 为了使用此方法,需要更新 List 操作以检索更多信息并将其传入视图,如图 7 所示
Controll代码如下:- public ActionResult List(int page = 1)
- {
- const int pageSize = 5;
-
- int totalRecords;
- IEnumerable<Product> products = productService.GetProducts(
- out totalRecords, pageSize:pageSize, pageIndex:page-1);
-
- PagedProductsModel model = new PagedProductsModel
- {
- PageSize= pageSize,
- PageNumber = page,
- Products = products,
- TotalRows = totalRecords
- };
- return View(model);
- }
复制代码 利用这些附加信息,即可更新视图以使用 WebGrid 的 Bind 方法。 通过调用 Bind 可提供要呈现的数据和总行数,并将 autoSortAndPage 参数设置为 false。 autoSortAndPage 参数告知 WebGrid 不需要应用分页,因为这由 List 方法负责。 对此可用下面代码说明- <div>
- @{
- var grid = new WebGrid<Product>(null, rowsPerPage: Model.PageSize,
- defaultSort:"Name");
- grid.Bind(Model.Products, rowCount: Model.TotalRows, autoSortAndPage: false);
- }
- @grid.GetHtml(columns: grid.Columns(
- grid.Column("Name", format: @<text>@Html.ActionLink(item.Name,
- "Details", "Product", new { id = item.ProductId }, null)</text>),
- grid.Column("ListPrice", header: "List Price",
- format: @<text>@item.ListPrice.ToString("0.00")</text>)
- )
- )
-
- </div>
复制代码 当然在上述代码中,您也可以指定一些样式:可以先将columns值赋值好,然后通过下面代码填充GetHtml- @grid.GetHtml(
- tableStyle: "ContactTB",
- headerStyle: "ContactHD",
- rowStyle: "Content",
- firstText: "首页",
- previousText: "上一页",
- nextText: "下一页",
- lastText: "末页",
- mode: WebGridPagerModes.All, //这段代码就是控制分页显示的样式,选择ALL,都兼容。
- columns: gridColumns
复制代码 Done, 这样分页就不会每次取出所有的数据了,而只会每次取出每页的数据。
由于关闭了 autoSortAndPage,排序功能遭到破坏。 WebGrid 利用查询字符串参数来传递排序列和方向,但我们已命令它不执行排序,所以WebGrid的方法介绍三介绍排序功能!
|
|