\n
摘要:在这个Tip中,你将学到如何扩展ASP.NET MVC框架,创建一个新的辅助方法,可以为数据库数据显示一个HTML表格。
\n
目前,ASP.NET MVC框架还没有包含任何直接等价于ASP.NET Web Forms GridView控件的东西。每次你需要显示数据时,你都必须编写所有的HTML和内联代码。在这个Tip中,我将向你展示图和为HtmlHelper类添加一个GridView()扩展方法。
\n
扩展方法是由一个类为另一个类添加的方法。你可以使用扩展方法来为现有的类添加更多的功能。在这里,我们将为HtmlHelper类——你在MVC视图页中常用的类——添加一个新的GridView()方法,用于为数据库数据呈现一个HTML表格。在Visual Basic .NET和C#中实现扩展方法有些不同。在Visual Basic .NET中创建扩展方法需要创建一个模块,然后用为模块中的函数添加特性。在C#中创建扩展方法需要创建一个静态类,并使用this关键字声明该静态类重的每个扩展方法的第一个参数。
\n
清单1列出了GridView()扩展方法的代码。
\n
清单1 – GridExtensions.cs
\n
view plaincopy to clipboardprint?
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq.Mapping;
using System.Data.Linq;
using System.Web.UI;
using System.Web.Mvc;
using System.Web;
namespace Tip8.Helpers
{
public static class GridExtensions
{
public static string GridView(this HtmlHelper htmlHelper, ITable table)
{
return GridView(htmlHelper, table, null, new GridViewOptions());
}
public static string GridView(this HtmlHelper htmlHelper, ITable table, string[] headers)
{
return GridView(htmlHelper, table, headers, new GridViewOptions());
}
public static string GridView(this HtmlHelper htmlHelper, ITable table, bool includeLinks)
{
return GridView(htmlHelper, table, null, includeLinks);
}
public static string GridView(this HtmlHelper htmlHelper, ITable table, string[] headers, bool includeLinks)
{
var options = new GridViewOptions();
if (!includeLinks)
{
options.ShowViewButton = false;
options.ShowEditButton = false;
options.ShowDeleteButton = false;
}
return GridView(htmlHelper, table, null, options);
}
public static string GridView(this HtmlHelper htmlHelper, ITable table, string[] headers, GridViewOptions options)
{
// Show edit column?
bool showEditColumn = options.ShowViewButton || options.ShowEditButton || options.ShowDeleteButton;
// Get identity column name
string identityColumnName = GridExtensions.GetIdentityColumnName(table);
// Get column names and headers
var columnNames = GridExtensions.GetColumnNames(table);
if (headers == null)
headers = columnNames;
// Open table
var sb = new StringBuilder();
sb.AppendLine(“<table>”);
// Create Header Row
sb.AppendLine(“<thead>”);
sb.AppendLine(“<tr>”);
if (showEditColumn)
sb.Append(“<th></th>”);
foreach (String header in headers)
sb.AppendFormat(“<th>{0}</th>”, header);
sb.AppendLine(“</tr>”);
sb.AppendLine(“</thead>”);
// Create Data Rows
sb.AppendLine(“<tbody>”);
sb.AppendLine(“<tr>”);
foreach (Object row in table)
{
if (showEditColumn)
{
int identityValue = (int)DataBinder.GetPropertyValue(row, identityColumnName);
sb.Append(“<td><small>”);
if (options.ShowViewButton)
{
sb.Append(htmlHelper.ActionLink(options.ViewButtonText, options.ViewAction, new { Id = identityValue }));
sb.Append(” “);
}
if (options.ShowEditButton)
{
sb.Append(htmlHelper.ActionLink(options.EditButtonText, options.EditAction, new { Id = identityValue }));
sb.Append(” “);
}
if (options.ShowDeleteButton)
{
sb.Append(htmlHelper.ActionLink(options.DeleteButtonText, options.DeleteAction, new { Id = identityValue }));
}
sb.Append(“</small></td>”);
}
foreach (string columnName in columnNames)
{
string value = DataBinder.GetPropertyValue(row, columnName).ToString();
sb.AppendFormat(“<td>{0}</td>”, HttpUtility.HtmlEncode(value));
}
sb.AppendLine(“</tr>”);
}
sb.AppendLine(“</tbody>”);
sb.AppendLine(“</table>”);
return sb.ToString();
}
public static string[] GetColumnNames(ITable table)
{
return table
.Context
.Mapping
.GetMetaType(table.ElementType)
.PersistentDataMembers.Select(m => m.Name)
.ToArray();
}
public static string GetIdentityColumnName(ITable table)
{
return table
.Context
.Mapping
.GetMetaType(table.ElementType)
.DBGeneratedIdentityMember
.Name;
}
}
}
using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using System.Data.Linq.Mapping;
using System.Data.Linq;
using System.Web.UI;
using System.Web.Mvc;
using System.Web;
namespace Tip8.Helpers
{
public static class GridExtensions
{
public static string GridView(this HtmlHelper htmlHelper, ITable table)
{
return GridView(htmlHelper, table, null, new GridViewOptions());
}
public static string GridView(this HtmlHelper htmlHelper, ITable table, string[] headers)
{
return GridView(htmlHelper, table, headers, new GridViewOptions());
}
public static string GridView(this HtmlHelper htmlHelper, ITable table, bool includeLinks)
{
return GridView(htmlHelper, table, null, includeLinks);
}
public static string GridView(this HtmlHelper htmlHelper, ITable table, string[] headers, bool includeLinks)
{
var options = new GridViewOptions();
if (!includeLinks)
{
options.ShowViewButton = false;
options.ShowEditButton = false;
options.ShowDeleteButton = false;
}
return GridView(htmlHelper, table, null, options);
}
public static string GridView(this HtmlHelper htmlHelper, ITable table, string[] headers, GridViewOptions options)
{
// Show edit column?
bool showEditColumn = options.ShowViewButton || options.ShowEditButton || options.ShowDeleteButton;
// Get identity column name
string identityColumnName = GridExtensions.GetIdentityColumnName(table);
// Get column names and headers
var columnNames = GridExtensions.GetColumnNames(table);
if (headers == null)
headers = columnNames;
// Open table
var sb = new StringBuilder();
sb.AppendLine(“<table>”);
// Create Header Row
sb.AppendLine(“<thead>”);
sb.AppendLine(“<tr>”);
if (showEditColumn)
sb.Append(“<th></th>”);
foreach (String header in headers)
sb.AppendFormat(“<th>{0}</th>”, header);
sb.AppendLine(“</tr>”);
sb.AppendLine(“</thead>”);
// Create Data Rows
sb.AppendLine(“<tbody>”);
sb.AppendLine(“<tr>”);
foreach (Object row in table)
{
if (showEditColumn)
{
int identityValue = (int)DataBinder.GetPropertyValue(row, identityColumnName);
sb.Append(“<td><small>”);
if (options.ShowViewButton)
{
sb.Append(htmlHelper.ActionLink(options.ViewButtonText, options.ViewAction, new { Id = identityValue }));
sb.Append(” “);
}
if (options.ShowEditButton)
{
sb.Append(htmlHelper.ActionLink(options.EditButtonText, options.EditAction, new { Id = identityValue }));
sb.Append(” “);
}
if (options.ShowDeleteButton)
{
sb.Append(htmlHelper.ActionLink(options.DeleteButtonText, options.DeleteAction, new { Id = identityValue }));
}
sb.Append(“</small></td>”);
}
foreach (string columnName in columnNames)
{
string value = DataBinder.GetPropertyValue(row, columnName).ToString();
sb.AppendFormat(“<td>{0}</td>”, HttpUtility.HtmlEncode(value));
}
sb.AppendLine(“</tr>”);
}
sb.AppendLine(“</tbody>”);
sb.AppendLine(“</table>”);
return sb.ToString();
}
public static string[] GetColumnNames(ITable table)
{
return table
.Context
.Mapping
.GetMetaType(table.ElementType)
.PersistentDataMembers.Select(m => m.Name)
.ToArray();
}
public static string GetIdentityColumnName(ITable table)
{
return table
.Context
.Mapping
.GetMetaType(table.ElementType)
.DBGeneratedIdentityMember
.Name;
}
}
}
清单1包含了GridView()方法的多个版本。每个版本的GridView()方法都接受一组不同的参数。例如,第一个版本的GridView()方法接受一个LINQ to SQL表,并呈现来自该表的所有列和行。其它版本的GridView()方法允许你自定义GridView的表头和编辑链接。
\n
清单2中的MVC视图展示了多种调用GridView()方法来展示数据表内容的方式。
\n
清单2 – Index.aspx
\n
view plaincopy to clipboardprint?
<%@ Page Language=”C#” MasterPageFile=”~/Views/Shared/Site.Master” AutoEventWireup=”true” CodeBehind=”Index.aspx.cs” Inherits=”Tip8.Views.Home.Index” %>
<%@ Import Namespace=”Tip8.Helpers” %>
<asp:Content ID=”indexContent” ContentPlaceHolderID=”MainContent” runat=”server”>
<h1>Simple Grid</h1>
<%= Html.GridView(ViewData.Model) %>
<h1>Simple Grid without Links</h1>
<%= Html.GridView(ViewData.Model, false) %>
<h1>Simple Grid with Custom Headers</h1>
<%= Html.GridView(ViewData.Model, new string[] {“AA”, “BB”, “CC”, “DD”} )%>
<h1>Simple Grid with Custom Links</h1>
<%= Html.GridView(ViewData.Model, null, new GridViewOptions { ViewButtonText = “Look”, ShowEditButton=false, ShowDeleteButton=false } )%>
</asp:Content>
<%@ Page Language=”C#” MasterPageFile=”~/Views/Shared/Site.Master” AutoEventWireup=”true” CodeBehind=”Index.aspx.cs” Inherits=”Tip8.Views.Home.Index” %>
<%@ Import Namespace=”Tip8.Helpers” %>
<asp:Content ID=”indexContent” ContentPlaceHolderID=”MainContent” runat=”server”>
<h1>Simple Grid</h1>
<%= Html.GridView(ViewData.Model) %>
<h1>Simple Grid without Links</h1>
<%= Html.GridView(ViewData.Model, false) %>
<h1>Simple Grid with Custom Headers</h1>
<%= Html.GridView(ViewData.Model, new string[] {“AA”, “BB”, “CC”, “DD”} )%>
<h1>Simple Grid with Custom Links</h1>
<%= Html.GridView(ViewData.Model, null, new GridViewOptions { ViewButtonText = “Look”, ShowEditButton=false, ShowDeleteButton=false } )%>
</asp:Content>
清单2中的视图生成了图1所示的HTML页。该页面包含四个单独的数据网格(图中只显示了前三个)。
\n
图1 – Index视图
\n
\n
注意ViewData.Model被传递到GridView()辅助方法中了。ViewData.Model包含了一个LINQ to SQL表。Index视图的code-behind文件为model指定了强类型System.Data.Linq.ITable。model是通过清单3所示的控制器代码传递到视图中的。
\n
清单3 – HomeController.cs
\n
view plaincopy to clipboardprint?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Tip8.Models;
namespace Tip8.Controllers
{
public class HomeController : Controller
{
private MovieDataContext _db = new MovieDataContext();
public ActionResult Index()
{
return View(_db.Movies);
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Tip8.Models;
namespace Tip8.Controllers
{
public class HomeController : Controller
{
private MovieDataContext _db = new MovieDataContext();
public ActionResult Index()
{
return View(_db.Movies);
}
}
}
我对该Tip中的这个GridView()辅助方法并不是非常满意。其问题在于使用扩展方法很难自定义GridView中列的外观。例如,我可能希望能够格式化现金和日期列。如果能够有与模板列等价的功能就更好了。在明天的Tip中,我将介绍在使用ASP.NET MVC框架时,一种完全不同的封装GridView的方法。
\n
此处下载源代码:http://weblogs.asp.net/blogs/stephenwalther/Downloads/Tip8/Tip8.zip。
\n
来源:http://www.cnblogs.com/AndersLiu
\n