http://blog.csdn.net/w678528/article/details/7782104
其中一个帮助组件是 WebGrid,该组件支持通过 AJAX 自定义列的格式、分页、排序和异步更新,使表格呈现变得非常简单。
msdn.microsoft.com/magazine/gg983489)。
msdn.microsoft.com/magazine/gg650669)。
WebGrid 入门
我的 ProductController 类有如下操作:
- public ActionResult List()
- {
- IEnumerable<Product> model =
- _productService.GetProducts();
- return View(model);
- }
图 1 所示的网格:
- @model IEnumerable<MsdnMvcWebGrid.Domain.Product>
- @{
- ViewBag.Title = "Basic Web Grid";
- }
- <h2>Basic Web Grid</h2>
- <div>
- @{
- var grid = new WebGrid(Model, defaultSort:"Name");
- }
- @grid.GetHtml()
- </div>
图 1 呈现的基本 Web 网格
该视图中的第一行指定型号(例如我们在视图中访问的 Model 属性的类型)为 IEnumerable<Product>。 然后,我在 div 元素内通过传入型号数据实例化一个 WebGrid,我将代码放入 @{...} 代码块中是要告诉 Razor 不要试图呈现结果。 我还在构造函数中将 defaultSort 参数设置为“Name”,告知 WebGrid 传给它的数据已按 Name 排序。 最后,我用 @grid.GetHtml() 生成网格的 HTML 并在响应中呈现网格。
如果需要自定义该行为,可在 WebGrid 构造函数和 GetHtml 方法中指定一些选项。 图 2 显示了 WebGrid 构造函数参数,图 3 显示了 GetHtml 参数。
图 2 WebGrid 构造函数参数
| 名称 | 类型 | 备注 |
| source | IEnumerable<dynamic> | 要呈现的数据。 |
| columnNames | IEnumerable<string> | 筛选呈现的列。 |
| defaultSort | string | 指定作为排序依据的默认列。 |
| rowsPerPage | int | 控制每页显示的行数(默认值为 10)。 |
| canPage | bool | 启用或禁用数据分页。 |
| canSort | bool | 启用或禁用数据排序。 |
| ajaxUpdateContainerId | string | 网格中包含元素的 ID,用来启用 AJAX 支持。 |
| ajaxUpdateCallback | string | 完成 AJAX 更新后调用的客户端函数。 |
| fieldNamePrefix | string | 支持多个网格时查询字符串字段使用的前缀。 |
| pageFieldName | string | 页码的查询字符串字段名称。 |
| selectionFieldName | string | 所选行号的查询字符串字段名称。 |
| sortFieldName | string | 排序列的查询字符串字段名称。 |
| sortDirectionFieldName | string | 排序方向的查询字符串字段名称。 |
图 3 WebGrid.GetHtml 参数
| 名称 | 类型 | 备注 |
| tableStyle | string | 样式使用的表类。 |
| headerStyle | string | 样式使用的标题行类。 |
| footerStyle | string | 样式使用的页脚行类。 |
| rowStyle | string | 样式使用的行类(仅限奇数行)。 |
| alternatingRowStyle | string | 样式使用的行类(仅限偶数行)。 |
| selectedRowStyle | string | 所选的样式行类。 |
| caption | string | 显示为表标题的字符串。 |
| displayHeader | bool | 指示是否应显示标题行。 |
| fillEmptyRows | bool | 指示表中是否可以通过添加空行来保证 rowsPerPage 的行数。 |
| emptyRowCellValue | string | 空行内填充的值,仅在设置了 fillEmptyRows 时使用。 |
| columns | IEnumerable<WebGridColumn> | 用于自定义列呈现的列模型。 |
| exclusions | IEnumerable<string> | 自动填充列时要排除的列。 |
| mode | WebGridPagerModes | 分页器呈现模式(默认值为 NextPrevious 和 Numeric)。 |
| firstText | string | 第一页链接的文本。 |
| previousText | string | 上一页链接的文本。 |
| nextText | string | 下一页链接的文本。 |
| lastText | string | 最后一页链接的文本。 |
| numericLinksCount | int | 要显示的数字链接的数量(默认值为 5)。 |
| htmlAttributes | object | 包含为元素设置的 HTML 属性。 |
前一段 Razor 代码将呈现每一行的所有属性,但您也可能希望对显示哪些列作出限制。 第一种方法(也是最简单的方法)是将这一组列传递到 WebGrid 构造函数。 例如,以下代码只呈现 Name 和 ListPrice 属性:
- var grid = new WebGrid(Model, columnNames: new[] {"Name", "ListPrice"});
在下面的示例中,我指定了 header 属性,以使 ListPrice 列更便于阅读:
- @grid.GetHtml(columns: grid.Columns(
- grid.Column("Name"),
- grid.Column("ListPrice", header:"List Price")
- )
- )
图 4 所示。
- @grid.GetHtml(columns: grid.Columns(
- grid.Column("Name", format: @<text>@Html.ActionLink((string)item.Name,
- "Details", "Product", new {id=item.ProductId}, null)</text>),
- grid.Column("ListPrice", header:"List Price",
- format: @<text>@item.ListPrice.ToString("0.00")</text>)
- )
- )
采用自定义列的基本网格
bit.ly/h0Q0Oz。
bit.ly/9GMoup)。
添加强类型化
如您所见,这是个非常轻型的包装!
创建派生 WebGrid
- 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);
- }
- }
不仅如此,现在还能够获得 IntelliSense 支持和编译器检查(假定项目文件中已经打开 MvcBuildViews,它默认处于关闭状态)。
无论采用哪种方式,返回的类型都是 WebGrid<Product>。
添加分页和排序
图 6 所示。
数据源中的项数
采用这种方式,只需要取回需要在当前页面中显示的数据(例如只显示五行数据)。
也就是说,您可以在自己的操作方法中采用一个名为 page 的参数,然后使用查询字符串值填充该参数。
图 7 所示。
更新 List 操作
- 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);
- }
对此可用下面代码说明:
- <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>
图 8 所示。
在操作方法中添加排序参数
- public ActionResult List(
- int page = 1,
- string sort = "Name",
- string sortDir = "Ascending" )
- {
- const int pageSize = 5;
- int totalRecords;
- IEnumerable<Product> products =
- _productService.GetProducts(out totalRecords,
- pageSize: pageSize,
- pageIndex: page - 1,
- sort:sort,
- sortOrder:GetSortDirection(sortDir)
- );
- PagedProductsModel model = new PagedProductsModel
- {
- PageSize = pageSize,
- PageNumber = page,
- Products = products,
- TotalRows = totalRecords
- };
- return View(model);
- }
AJAX:客户端改动
指定 ajaxUpdateContainerId 以后,WebGrid 会修改自己的行为,使分页和排序链接能够利用 AJAX 进行更新:
- <div id="grid">
- @{
- var grid = new WebGrid<Product>(null, rowsPerPage: Model.PageSize,
- defaultSort: "Name", ajaxUpdateContainerId: "grid");
- grid.Bind(Model.Products, autoSortAndPage: false, rowCount: Model.TotalRows);
- }
- @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>
其原因在于,在 AJAX 模式下,WebGrid 在呈现定位标记时将 href 设置为“#”,并通过 onclick 处理程序注入 AJAX 行为。
图 9 所示的脚本以重新应用 AJAX 行为:
重新应用 AJAX 行为
- $(document).ready(function () {
- function updateGrid(e) {
- e.preventDefault();
- var url = $(this).attr('href');
- var grid = $(this).parents('.ajaxGrid');
- var id = grid.attr('id');
- grid.load(url + ' #' + id);
- };
- $('.ajaxGrid table thead tr a').live('click', updateGrid);
- $('.ajaxGrid table tfoot tr a').live('click', updateGrid);
- });
这将为符合选择器要求的现有和未来元素设置事件处理程序,由于脚本将取代内容,因此这样做非常方便。
图 9 所示的脚本。
AJAX:服务器端改动
但是,load(‘http://example.com/someurl #someId’) 将从指定 URL 加载内容,然后返回 id 为“someId”的片段。这反映了 WebGrid 的默认 AJAX 行为,意味着不必通过更新服务器代码添加部分呈现行为。WebGrid 首先加载整个页面,然后从中剥离出新的网格。
随后,控制器中的 List 操作既可以为 AJAX 调用仅呈现部分视图,也可以为非 AJAX 调用呈现完整视图(该完整视图又使用该部分视图)。
bit.ly/eMlIxU 的博客文章。
WebGrid 和 WebForms 视图引擎
在前面的示例中,我演示了如何使用 format 参数自定义行数据的呈现:
- grid.Column("Name",
- format: @<text>@Html.ActionLink((string)item.Name,
- "Details", "Product", new { id = item.ProductId }, null)</text>),
不过,您还是可以传递 Func,例如用 lambda 表达式:
- grid.Column("Name",
- format: item => Html.ActionLink((string)item.Name,
- "Details", "Product", new { id = item.ProductId }, null)),
借助于这种简单的转换,现在我们可以轻松地在 WebForms 视图引擎中使用 WebGrid!
总结
希望本文能为您在 ASP.NET MVC 应用程序中充分利用 WebGrid 提供有益的提示。