http://blog.csdn.net/w678528/article/details/7782104

其中一个帮助组件是 WebGrid,该组件支持通过 AJAX 自定义列的格式、分页、排序和异步更新,使表格呈现变得非常简单。

msdn.microsoft.com/magazine/gg983489)。

msdn.microsoft.com/magazine/gg650669)。

WebGrid 入门

我的 ProductController 类有如下操作:

  1.  
  2.           public ActionResult List()
  3.   {
  4.     IEnumerable<Product> model =
  5.       _productService.GetProducts();
  6.  
  7.     return View(model);
  8.   }
  9.         

图 1 所示的网格:

  1.  
  2.           @model IEnumerable<MsdnMvcWebGrid.Domain.Product>
  3. @{
  4.   ViewBag.Title = "Basic Web Grid";
  5. }
  6. <h2>Basic Web Grid</h2>
  7. <div>
  8. @{
  9.   var grid = new WebGrid(Model, defaultSort:"Name");
  10. }
  11. @grid.GetHtml()
  12. </div>
  13.         

(单击进行缩放)

图 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 属性:

  1.  
  2.           var grid = new WebGrid(Model, columnNames: new[] {"Name", "ListPrice"});
  3.         

在下面的示例中,我指定了 header 属性,以使 ListPrice 列更便于阅读:

  1.  
  2.           @grid.GetHtml(columns: grid.Columns(
  3.  grid.Column("Name"),
  4.  grid.Column("ListPrice", header:"List Price")
  5.  )
  6. )
  7.         

图 4 所示。

  1.  
  2.           @grid.GetHtml(columns: grid.Columns(
  3.  grid.Column("Name", format: @<text>@Html.ActionLink((string)item.Name,
  4.             "Details", "Product", new {id=item.ProductId}, null)</text>),
  5.  grid.Column("ListPrice", header:"List Price", 
  6.              format: @<text>@item.ListPrice.ToString("0.00")</text>)
  7.  )
  8. )
  9.         

在 ASP.NET MVC 中充分利用 WebGrid

采用自定义列的基本网格

bit.ly/h0Q0Oz。

bit.ly/9GMoup)。

添加强类型化

如您所见,这是个非常轻型的包装!

创建派生 WebGrid

  1.  
  2.           public class WebGrid<T> : WebGrid
  3.   {
  4.     public WebGrid(
  5.       IEnumerable<T> source = null,
  6.       ...
  7.           parameter list omitted for brevity)
  8.     : base(
  9.       source.SafeCast<object>(), 
  10.       ...
  11.           parameter list omitted for brevity)
  12.     { }
  13.   public WebGridColumn Column(
  14.               string columnName = null, 
  15.               string header = null, 
  16.               Func<T, object> format = null, 
  17.               string style = null, 
  18.               bool canSort = true)
  19.     {
  20.       Func<dynamic, object> wrappedFormat = null;
  21.       if (format != null)
  22.       {
  23.         wrappedFormat = o => format((T)o.Value);
  24.       }
  25.       WebGridColumn column = base.Column(
  26.                     columnName, header, 
  27.                     wrappedFormat, style, canSort);
  28.       return column;
  29.     }
  30.     public WebGrid<T> Bind(
  31.             IEnumerable<T> source, 
  32.             IEnumerable<string> columnNames = null, 
  33.             bool autoSortAndPage = true, 
  34.             int rowCount = -1)
  35.     {
  36.       base.Bind(
  37.            source.SafeCast<object>(), 
  38.            columnNames, 
  39.            autoSortAndPage, 
  40.            rowCount);
  41.       return this;
  42.     }
  43.   }
  44.  
  45.   public static class WebGridExtensions
  46.   {
  47.     public static WebGrid<T> Grid<T>(
  48.              this HtmlHelper htmlHelper,
  49.              ...
  50.           parameter list omitted for brevity)
  51.     {
  52.       return new WebGrid<T>(
  53.         source, 
  54.         ...
  55.           parameter list omitted for brevity);
  56.     }
  57.   }
  58.         

不仅如此,现在还能够获得 IntelliSense 支持和编译器检查(假定项目文件中已经打开 MvcBuildViews,它默认处于关闭状态)。

无论采用哪种方式,返回的类型都是 WebGrid<Product>。

添加分页和排序

图 6 所示。

在 ASP.NET MVC 中充分利用 WebGrid

数据源中的项数

采用这种方式,只需要取回需要在当前页面中显示的数据(例如只显示五行数据)。

也就是说,您可以在自己的操作方法中采用一个名为 page 的参数,然后使用查询字符串值填充该参数。

图 7 所示。

更新 List 操作

  1.  
  2.           public ActionResult List(int page = 1)
  3. {
  4.   const int pageSize = 5;
  5.  
  6.   int totalRecords;
  7.   IEnumerable<Product> products = productService.GetProducts(
  8.     out totalRecords, pageSize:pageSize, pageIndex:page-1);
  9.             
  10.   PagedProductsModel model = new PagedProductsModel
  11.                                  {
  12.                                    PageSize= pageSize,
  13.                                    PageNumber = page,
  14.                                    Products = products,
  15.                                    TotalRows = totalRecords
  16.                                  };
  17.   return View(model);
  18. }
  19.         

对此可用下面代码说明:

  1.  
  2.           <div>
  3. @{
  4.   var grid = new WebGrid<Product>(null, rowsPerPage: Model.PageSize, 
  5.     defaultSort:"Name");
  6.   grid.Bind(Model.Products, rowCount: Model.TotalRows, autoSortAndPage: false);
  7. }
  8. @grid.GetHtml(columns: grid.Columns(
  9.  grid.Column("Name", format: @<text>@Html.ActionLink(item.Name, 
  10.    "Details", "Product", new { id = item.ProductId }, null)</text>),
  11.   grid.Column("ListPrice", header: "List Price", 
  12.     format: @<text>@item.ListPrice.ToString("0.00")</text>)
  13.   )
  14.  )
  15.  
  16. </div>
  17.         

图 8 所示。

在操作方法中添加排序参数

  1.  
  2.           public ActionResult List(
  3.            int page = 1, 
  4.            string sort = "Name", 
  5.            string sortDir = "Ascending" )
  6. {
  7.   const int pageSize = 5;
  8.  
  9.   int totalRecords;
  10.   IEnumerable<Product> products =
  11.     _productService.GetProducts(out totalRecords,
  12.                                 pageSize: pageSize,
  13.                                 pageIndex: page - 1,
  14.                                 sort:sort,
  15.                                 sortOrder:GetSortDirection(sortDir)
  16.                                 );
  17.  
  18.   PagedProductsModel model = new PagedProductsModel
  19.   {
  20.     PageSize = pageSize,
  21.     PageNumber = page,
  22.     Products = products,
  23.     TotalRows = totalRecords
  24.   };
  25.   return View(model);
  26. }
  27.         

AJAX:客户端改动

指定 ajaxUpdateContainerId 以后,WebGrid 会修改自己的行为,使分页和排序链接能够利用 AJAX 进行更新:

  1.  
  2.           <div id="grid">
  3.  
  4. @{
  5.   var grid = new WebGrid<Product>(null, rowsPerPage: Model.PageSize, 
  6.   defaultSort: "Name", ajaxUpdateContainerId: "grid");
  7.   grid.Bind(Model.Products, autoSortAndPage: false, rowCount: Model.TotalRows);
  8. }
  9. @grid.GetHtml(columns: grid.Columns(
  10.  grid.Column("Name", format: @<text>@Html.ActionLink(item.Name, 
  11.    "Details", "Product", new { id = item.ProductId }, null)</text>),
  12.  grid.Column("ListPrice", header: "List Price", 
  13.    format: @<text>@item.ListPrice.ToString("0.00")</text>)
  14.  )
  15. )
  16.  
  17. </div>
  18.         

其原因在于,在 AJAX 模式下,WebGrid 在呈现定位标记时将 href 设置为“#”,并通过 onclick 处理程序注入 AJAX 行为。

图 9 所示的脚本以重新应用 AJAX 行为:

重新应用 AJAX 行为

  1.  
  2.           $(document).ready(function () {
  3.  
  4.   function updateGrid(e) {
  5.     e.preventDefault();
  6.     var url = $(this).attr('href');
  7.     var grid = $(this).parents('.ajaxGrid'); 
  8.     var id = grid.attr('id');
  9.     grid.load(url + ' #' + id);
  10.   };
  11.   $('.ajaxGrid table thead tr a').live('click', updateGrid);
  12.   $('.ajaxGrid table tfoot tr a').live('click', updateGrid);
  13.  });
  14.         

这将为符合选择器要求的现有和未来元素设置事件处理程序,由于脚本将取代内容,因此这样做非常方便。

图 9 所示的脚本。

AJAX:服务器端改动

但是,load(‘http://example.com/someurl #someId’) 将从指定 URL 加载内容,然后返回 id 为“someId”的片段。这反映了 WebGrid 的默认 AJAX 行为,意味着不必通过更新服务器代码添加部分呈现行为。WebGrid 首先加载整个页面,然后从中剥离出新的网格。

随后,控制器中的 List 操作既可以为 AJAX 调用仅呈现部分视图,也可以为非 AJAX 调用呈现完整视图(该完整视图又使用该部分视图)。

 bit.ly/eMlIxU 的博客文章。

WebGrid 和 WebForms 视图引擎

在前面的示例中,我演示了如何使用 format 参数自定义行数据的呈现:

  1.  
  2.           grid.Column("Name", 
  3.   format: @<text>@Html.ActionLink((string)item.Name, 
  4.   "Details", "Product", new { id = item.ProductId }, null)</text>),
  5.         

不过,您还是可以传递 Func,例如用 lambda 表达式:

  1.  
  2.           grid.Column("Name", 
  3.   format: item => Html.ActionLink((string)item.Name, 
  4.   "Details", "Product", new { id = item.ProductId }, null)),
  5.         

借助于这种简单的转换,现在我们可以轻松地在 WebForms 视图引擎中使用 WebGrid!

总结

希望本文能为您在 ASP.NET MVC 应用程序中充分利用 WebGrid 提供有益的提示。

相关文章: