弃用DataGrid,使用GridView结合DetailsView

本文讨论ASP.NET 2.0 技术
• ASP.NET 2.0 GridView、FormView 和 DetailsView
• DataGrid 和 GridView 的差异
• 这些控件的编程接口
• 如何完成主/详细视图

示例代码下载:
GridView.exe

更多相关文章可查阅本站:
(.Net企业开发)patterns & practices 企业程序库
(.Net企业开发)企业程序库(一)——缓存应用程序块简介
(.Net企业开发)企业程序库(二)——配置应用程序块简介
(.Net企业开发)企业程序库(三)——数据访问应用程序块
(.Net企业开发)企业程序库(四)——加密应用程序块简介
(.Net企业开发)之企业程序库(五)——异常处理应用程序块简介
(.Net企业开发)之企业程序库(六)——日志和规范应用程序块简介
(.Net企业开发)之企业程序库(七)——安全应用程序块
ASP.NET 2.0中的DataSource控件
使用ASP.NET 2.0中的GridView控件
在ASP.NET 2.0中使用页面导航控件
详细研究Asp.Net中的DataReader(附代码)
Asp.Net中使用DataReader对象
ASP.NET 数据访问类

    尽管有丰富、功能强大的编程接口,ASP.NET 1.x DataGrid 控件仍需要编写大量自定义代码来处理普通操作,如分页、排序、编辑和删除数据。
   例如,当用户单击以保存或取消更改时,DataGrid 控件能够引发事件但不提供更多的功能。如果要将更改存储到持续媒介(如一个数据库)之中,则必须自己处理 UpdateCommand 事件,检索更改后的值,编写一条 SQL 命令,然后从该处提交更新。
   DataGrid 控件限制普通数据操作的引发事件,因为它是一个数据源不可知的控件,能够绑定到任何可枚举的数据对象。执行数据操作(如更新或删除)需要直接连接到一个特定的数据源。在 ASP.NET 1.x 中,则通过编写特定于应用程序的 ADO.NET 代码解决这个问题的。
   ASP.NET 2.0 改进了数据绑定体系结构,引入了新的系列组件(数据源对象)作为数据绑定控件与 ADO.NET 对象之间的桥梁。这些源对象提升了一个略为不同的编程模型,提供了新功能和新成员。您的 ASP.NET 2.0 应用程序应该使用最新的网格控件 — GridView,显示数据报告。与之相似的 DataGrid 控件仍然支持,但 DataGrid 不能充分利用数据源组件的特定功能。
GridView 控件是 DataGrid 的接替者,并从几个方面扩展了后者的功能。首先,它完全支持数据源组件,能够自动处理诸如分页、排序和编辑等数据操作,前提是绑定的数据源对象支持这些操作。另外,GridView 控件有一些比 DataGrid 优越的功能上的改进。特别是,它支持多个主键字段,公开了一些用户界面的改进功能和一个处理与取消事件的新模型。
GridView 附带了一对互补的视图控件:DetailsView 和 FormView。通过这些控件的组合,您能够轻松地建立主/详细视图,而只需少量代码,有时根本不需要代码。

  DetailsView 控件
  DetailsView 控件与 GridView 控件相似,它使用完全相同的安装机制。GridView 控件在一页显示多条记录,而 DetailsView 控件一次只显示一条记录。

图 9. 在 DetailsView 控件中显示一条记录

  因此,DetailsView 控件与 GridView 控件形成了很好的互补。将 DetailsView 连接到 GridView 可以更好地控制更新个别项目或插入新项目的方式和时机。
  FormView 控件
  使用上述配置步骤,我们还能够为 ASP.NET 的开发配置另一个新控件 — FormView 控件。FormView 控件支持非常灵活的 UI 布局。下面的示例显示使用 FormView 控件查看单个数据库记录。

图 10. FormView ItemTemplate 输出
  像 ItemTemplate 和 EditItemTemplate 这样不同的模板用于查看和修改数据库记录,无需任何自定义代码。

图 11. FormView EditTemplate 输出


GridView 与 DataGrid
ASP.NET 2.0 中数据绑定控件的类层次结构比 ASP.NET 1.x 中的更一致。在 2.0 版本中,所有控件无论有什么样的实际实现过程和用户界面特点,均从同一个基类(BaseDataBoundControl 类)派生。图 1 显示新的类关系图。DataGrid 和其他 1.x 版本的控件(如 Repeater 和 DataList)没有包含在该关系图中。这些现有控件的继承树与 ASP.NET 1.x 的相同。特别是,Repeater 继承了 WebControl,而 DataList 和 DataGrid 继承了 BaseDataList。如图 1 所示,GridView 是一个复合数据绑定控件,它与其他所有数据绑定控件(包括 DropDownList、DetailsView 和 ListBox)共享一组方法和属性。

图 1 ASP.NET 类关系图
GridView 和 DataGrid 控件的高级功能相似,但基础却不同。GridView 尽可能地保留了 DataGrid 的对象模型,以便轻松地从现有页面进行移植。但是,基于 DataGrid 的代码与新的基于 GridView 的代码不可能 100% 兼容。
DataGrid 与 GridView 控件的另一个主要差异在于自适应用户界面。与 1.x 版本的 DataGrid 不同的是,GridView 也能在移动设备上显示。换句话说,您能够使用相同的用于桌面页面的网格控件在移动设备上生成报告。2.0 版本的 DataGrid 也能自适应地显示,但是它的 UI 功能没有 GridView 丰富。
在 ASP.NET 2.0 中,改进后的 DataGrid 控件支持诸如主题和个性化等通用的控件功能。此外,新的 DataGrid 控件可由一个数据源控件填充。但要记住,绑定到数据源对象的 DataGrid 只能用于读取数据。要实际修改底层数据源,仍然需要一些用户定义的代码。而 GridView 控件可以利用底层数据源的功能并自动删除或更新记录。注意,GridView 控件也支持传统的基于 DataSource 属性和 DataBind 方法的绑定机制。尽管完全支持这种绑定机制,但是不鼓励使用这样的编程实践方法。

GridView 和数据源控件
那么,数据源控件是什么?我在 2004 年 6 月一期的 MSDN®Magazine 中详细介绍了 ASP.NET 2.0 的这项流行的新功能。简言之,一个数据源控件就是一组 Microsoft® .NET Framework 类,它有利于数据存储和数据绑定控件之间的双向绑定。现有的控件(如 DataGrid)以及新的数据绑定控件(如 GridView),尽管绑定能力不同,但都能绑定到一个数据源。
一个数据源控件代表了数据源的主要功能:选择、插入、更新和删除。数据源控件能代表任何数据源:从关系数据源库到 XML 文件,从流数据到业务对象。如果简要介绍能让您想起 .NET 的托管提供程序,请参见图 2。

图 2 数据源控件、GridView 和数据源

数据源控件可以位于一些 .NET 数据提供程序的上层,在数据绑定控件和数据源之间形成一个中间层。数据源控件也会公开一个提供基本操作的公共接口。一些数据绑定控件 — 特别是 GridView 控件,将这些命令与其他与数据有关的操作一起,绑定到适当的自动编辑。
数据源控件通过其属性和方法,将绑定内容以一组命名的视图形式公开。IDataSource 接口提供从数据源检索数据视图的基本功能集,所有数据源控件都实现了这个接口。ASP.NET 2.0 提供一些内置数据源控件,如图 3 所列。图 3列出的数据源控件属于两类:列表和分层组件。SiteMapDataSource 和 XmlDataSource 组件是分层数据源控件,用于像 TreeView 和 Menu 控件这样的分层组件。其他各种组件用于管理列表数据。
图 4 中的代码说明如何在一个示例页面上将 GridView 和 DataGrid 绑定到同一个数据源控件。在 ASP.NET 2.0 中,这是推荐的数据绑定方法。SqlDataSource 控件的特点是一个 ConnectionString 属性加上 SelectCommand、UpdateCommand、InsertCommand 和 DeleteCommand 属性的任意组合。所有属性都是字符串形式,并且引用带有可选参数的命令文本:
程序代码 程序代码
<asp:SqlDataSource runat="server"
  ID="MySource"
  ConnectionString="SERVER=(local);
  DATABASE=northwind;Integrated Security=SSPI;"
  SelectCommand="Select * FROM employees Where employeeid > @MinID">
  <SelectParameters>
     <asp:ControlParameter Name="MinID"
          ControlId="EmpID"
          PropertyName="Text" />
  </SelectParameters>
</asp:SqlDataSource>


每个数据源控件由唯一的 ID 表示。ID 是连结数据绑定控件和数据源控件之间的纽带。通过 DataSourceId 属性将 GridView 绑定到一个数据源控件。例如,每当网格需要获取数据时,就执行与 SQLDataSource 控件相关联的 SelectCommand SQL 命令。当网格需要更新或删除一条记录时,就执行相应的 UpdateCommand 或 DeleteCommand SQL 命令。如果不存在这样的命令,则引发一个异常。在内部,当用户删除或更新一条记录时,GridView 就像 1.x 版本的 DataGrid 一样引发事件。但是与 DataGrid 不同的是,GridView 为这些事件定义内部的处理程序。默认的处理程序检索绑定数据源定义的命令来处理和执行这些操作。图 4说明,在保持网格显示或更新数据的标记后无需编写代码。在更复杂的情况下,您可能需要编写一些代码。

图 5 GridView 和 DataGrid

数据源控件和 GridView 控件通常用于无代码数据绑定。图 5 显示图 4的代码生成的输出结果。
在 ASP.NET 2.0 中,除了 DataSource 和 DataMember,DataGrid 还公开了 DataSourceId 属性。DataSourceId 属性将 DataGrid 连接到同一页面上定义的一个合法数据源对象。但是,DataGrid 不提供与 GridView 同一级别的自动化操作。当用户单击以更新一条记录时,DataGrid 引发 UpdateCommand 事件,而 GridView 除了引发 Updating 和 Updated 事件外,还检索和执行数据源更新命令,允许用户自定义发送到数据源控件的信息。

GridView 对象模型
GridView 与 DataGrid 的整体结果看起来相似。一些通用元素经过了重命名,一些通用功能现在需要不同的语法。总之,如果熟悉 DataGrid 控件,则可立即自如地运用 GridView。图 6 详尽列出了组成 GridView 的新元素(请注意,其中一些元素,如 DetailLinkStyle,仅用于在移动设备上显示网格)。行元素通过 Rows 集合中的 GridViewRow 类生成的实例进行显示。GridViewRow 类映射到 DataGridItem 类,而 Rows 明确替代了 DataGrid 的项目集合。行类型由 DataControlRowType 枚举表示,用来指示位置和角色(例如,页脚、页眉、页导航和数据行)。GridView 还引入一个新概念 — 行元素状态。该行状态由 DataControlRowState 标记的枚举值表示 — 通常值是 Edit,可选值为 Insert 和 Selected。有趣的是,这两类枚举恰巧由所有数据视图控件(GridView、DetailsView 和 FormView)共享。
除了引入符合自适应显示的元素之外,GridView 仅有一个其他类型的新元素 — 空数据行。当 GridView 绑定到一个空数据源时,会选择性地显示一些默认内容,为用户提供反馈。在这种情况下显示的内容依赖于新的空数据行元素的内容。可通过一个属性 (EmptyDataText) 或一个模板 (EmptyDataTemplate) 设置该行的内容。
GridView 控件的属性主要分为三种类型:行为、可视设置和状态。图 7 列出 GridView 的一些属性。请查看包括 EnableSortingAndPagingCallbacks、EmptyDataText 和 UseAccessibleHeader 在内的新属性以及被重命名或改编的属性,后者实现了 DataGrid 已经支持的功能。
编程模型与按钮列略有不同。在 ASP.NET 1.x 的 DataGrid 中,您不得不通过添加特定的列类型来创建一个 Edit 按钮 — EditCommandColumn。如果要创建一个 Delete 或 Select 按钮列,则必须添加通用的按钮列并预定义一个命令名。GridView 对象则更一致、更简洁。它基于三个新的布尔属性:AutoGenerateEditButton、AutoGenerateDeleteButton 和 AutoGenerateSelectButton。当其中任何一个属性设置为真时,网格中分别添加一个 Edit、Delete 或 Select 命令按钮列。例如,当 AutoGenerateEditButton 属性设置为真时,在网格中自动为每个数据行添加带有 Edit 按钮的一列。也可以手动添加这些按钮,方法是在列集合中添加一个 CommandField 对象。Columns 属性列出了列对象,这些对象很像 DataGrid 的 Columns 属性列出的对象。根据客户的反馈,其中也添加了几个帮助器属性。特别是,您现在能够为每个显示行存储多个键值。实际上,DataGrid 的 DataKeyField 字符串属性已经扩展为一个字段名数组。新的属性命名为 DataKey,用于存储由字段名组成的一个字符串数组,这个字符串数组唯一标识一个数据行。DataKey 是特定行的值的相应数组。它返回 DataKey 对象的集合。每个 DataKey 对象包含一个键名值,DataKey 的 DataKey 对象数量与 GridView 的显示行数相同。
SortDirection 和 SortExpression 跟踪当前的网格排序。这些属性用于在内部实现自动翻转排序,标记网格当前排序次序。每个对象的 PagerSettings 组包含配置用户界面、行为和页导航位置的所有属性。现在,页导航支持的导航模式不但包括首行和尾行,还包括下一行和上一行。
GridView 控件也能够使用一个基于回调的轻量型机制来进行排序和分页。您可以通过设置 EnableSortingAndPagingCallbacks 布尔属性来开启和关闭此功能。当单击排序或分页链接来启用回调时,GridView 请求排序数据或下一页,不回发可视页面。(这里发生了一个往返过程,但是无页面刷新,因此您不知道。)请注意,这个功能有个警告:启用 GridView 中的选项时,新页面保留当前选定的索引。如果有与之相关联的详细信息页面,那么选定的内容将失去同步。处理类似 PageIndexChanging 这样的事件也不管用,因为如果不启用回调,则不能引发这些事件。最后,切记回调驱动的分页和排序机制需要使用 Microsoft Internet Explorer 5.0 及更高版本。

GridView 事件
GridView 控件使用的方法与我们熟知的 DataBind 方法不同。在 ASP.NET 2.0 中,许多控件以及 Page 类本身使用的是 Pre-load/Post-load 事件对。控件生命周期中的关键操作被包装在一对事件中,一个在操作发生前触发,另一个在操作完成后立即触发。GridView 类也是这样。图 8 显示的是新事件列表。使用事件来通告操作极大地增强了编程能力。例如,通过挂钩 RowUpdating 事件,您能够检查新值的更新内容。您可能想在客户端提供的值存留到下层数据存储之前,通过 HTML 编码来处理 RowUpdating 事件。这种简单的技巧有助于避免恶意的脚本注入。
使用 pre/post 事件对使您能够取消一个基于运行时条件而进行的事件。请看以下代码片段:
程序代码 程序代码
void PageIndexChanging(object sender, GridViewPageEventArgs e)
{
  // Is this the sensitive page? (> 4)
  bool isSensitivePage = (e.NewPageIndex > 4);
  if (isSensitivePage && (User.Identity.Name != "username"))
     e.Cancel = true;
  return;    
}

取消是一个读/写布尔属性,存在于所有从 CancelEventArgs 派生的事件参数类中。GridView 的许多事件参数类继承了 CancelEventArgs,这意味着所有这些事件都能被取消。Cancel 属性值在激发“pre”事件时通常设置为假。处理事件时,您能够检查一些条件,通过将 Cancel 属性设置为真选择取消事件。例如,刚才的代码片段在当前用户未被授权查看索引大于 4 的页面时,取消了转换到新页面的操作。

显示、排序和分页
一个网格通常用于显示数据库查询的结果。使用 GridView 控件显示结果比以往更简单。您只需建立一个数据源对象,提供连接字符串和查询文本,为 GridView 的 DataSourceId 属性分配数据源 ID。运行时,GridView 自动绑定到数据源,生成正确的数据列。在默认情况下,查询的所有列均显示在网格中。
像 DataGrid 控件一样,GridView 也支持在 Columns 集合中自定义列字段。如果只想显示检索到的数据字段的一个子集,或只想自定义其显示外观,则可使用代表显示数据列的对象来填充 Columns 集合。GridView 支持多种列类型,包括新的复选框和图像列类型:
程序代码 程序代码
<columns>
  <asp:boundfield datafield="productname" headertext="Product" />
  <asp:checkboxfield datafield="discontinued"
     headertext="Discontinued" />
  <asp:buttonfield buttontype="Button" text="Buy" />
  <asp:hyperlinkfield text="More Info…"
     datanavigateurlfields="productid,discontinued"
     datanavigateurlformatstring="more.aspx?id={0}&disc={1}" />
</columns>

图 9 显示的活动网格配置为使用代码中列出的字段。GridView 列类名与 DataGrid 接口中的相应类名略有不同。后缀“column”基本被替换成后缀“field”。除了名字的更改,与列类匹配的行为几乎相同。一些新的列类型使您不必经常使用模板。例如,CheckBoxField 列通过一个复选框显示特定的数据字段,而改进的 HyperLinkField 列提供了期待已久的功能 — 支持多个 URL 参数。正如刚才的代码片段所示,DataNavigateUrlFields 属性接收了一个以逗号分隔的字段名列表,并将其合并到 DataNavigateUrlFormatString 属性的文本中。

图 9 带有活动字段的 GridView
请注意 ButtonField 与 CommandField 之间的差异。两列都向网格的用户界面添加了一个按钮,但是 CommandField 用于显示命令按钮来执行选择、编辑、插入或删除操作。ButtonField 只是代表作为按钮显示的字段。最后,GridView 能够通过 ImageField 列类型嵌入图像。
<asp:imagefield datafield="photo" headertext="Picture" />

图 10 显示活动的 ImageField 列,它位于 Northwind 雇员表的照片字段。有趣的是,ImageField 通过 ASP.NET 2.0 DynamicImage 控件显示来自数据库和 URL 两者的图像。而且,在编辑模式下,ImageField 列弹出一个 Browse 按钮,用于定位要上载的位于本机的新文件。

图 10 图像字段列
Template 列也受支持,所需的语法与 ASP.NET 1.x 的 DataGrid 使用的相似:
程序代码 程序代码
<asp:templatefield headertext="Product">
   <itemtemplate>
     <b><%# Eval("productname")%></b> <br />
     available in <%# Eval("quantityperunit")%>
  </itemtemplate>
</asp:templatefield>


有趣的是,ASP.NET 2.0 允许的数据绑定表达式的语法更简洁。在 ASP.NET 1.x 中生成模板化的内容需要使用下列表达式: DataBinder.Eval(Container.DataItem, "fieldname")由于使用了一个更小的数据绑定机制,现在,您能够避免使用 DataBinder 类中静态的 Eval 方法,而是调用 Page 类定义的新的 Eval 保护方法。您将计算的字段名和方法传递给 Eval,决定当前的数据项并通过 DataBinder.Eval 准备一个常规调用。
Eval 被声明为 TemplateControl 类的一个保护方法,Page 和 UserControl 都从这个类派生。真正代表一个 .aspx 活动页面的类是从 Page 派生的一个类的实例;因此,它能够调入受保护的方法。ASCX 用户控件也是如此。
如果焦点是显示纯数据,则不需要像 GridView 这样全新的网格控件。当然,现在您只需少量代码或不需要编码就能将数据源控件绑定到 GridView,但是单凭这点就有必要替换 DataGrid 吗?如果答案是否定的,请考虑排序和分页。
在 GridView 控件中,只需通过开启 AllowPaging 和 AllowSorting 属性就能启用自动翻转排序和分页功能。如果在 ASP.NET 1.x 中尝试过这项操作,您就可大概了解这项功能了。

图 11 活动的可分页、可排序网格

图 11 显示一个可分页、可排序的网格。图 12 显示此网格的完整代码。(值得注意的是,仅当需要标记列标头来指示排序方向时才需要使用 C# 代码。)因此,无需编写代码,排序和分页就能十分正常地运行。通过 DataSourceMode 属性控制 SQLDataSource 的数据检索模型。可行的值类型是 DataSet(默认值)和 DataReader。当 DataSourceMode 为 DataSet 时,数据源控件可能会一直选择性地缓存 Select 命令的结果。这使得 GridView 适应于丰富多样的使用情境,其中控件可提供无代码排序、筛选和分页功能。默认情况下禁用缓存,因此它必须在数据源控件上启用。
在内存中缓存数据能大大提高性能,但是数据会显得有些脆弱。您必须权衡利弊,因为如果系统内存运行效率低,Cache 对象会自动丢弃最少使用的数据。此外,在 ASP.NET 2.0 中,SQLDataSource 控件可能选择性地建立与数据库的自动依赖关系,以便立即检测到数据变更。这确保了总是显示最新的数据。有关数据源控件功能的更多信息,请参见我在前面提到的 2004 年 6 月发表的文章。当 SQLDataSource 控件检索模型为 DataReader 时,检索数据使用 IDataReader 对象,它是一个只进、只读、流水游标。

编辑数据
DataGrid 控件最大的缺点之一 — 相反却是 GridView 控件最大的优点之一,是处理数据源更新的能力。当绑定数据源支持更新时,GridView 能够自动执行数据操作,从而提供真正的出盒解决方案。数据源控件通过一些布尔属性(例如 CanUpdate、CanDelete、CanSort 等)提供这些功能。
对 GridView 控件而言,数据编辑意味着就地编辑和记录删除。如前所述,就地编辑指网格支持更改当前显示记录的功能。启用 GridView 的就地编辑,需要启动 AutoGenerateEditButton 布尔属性:
<asp:gridview runat="server" id="MyGridView"
   datasourceid="MySource"
   autogenerateeditbutton="true">
   •••
</asp:gridview>
当 AutoGenerateEditButton 属性设置为真时,GridView 显示附加的一列,如图 13 中最左边一列。单击一行的 Edit 按钮将此行置于编辑模式下。当一行处于编辑模式下时,非只读行的每个绑定字段将显示适当的输入控件,通常是一个 TextBox。当您单击更新时,GridView 引发 RowUpdating 事件并检查数据源的 CanUpdate 属性。如果 CanUpdate 返回值为假,则引发一个异常。否则,在数据源对象的 UpdateCommand 属性后创建和配置一个命令对象。

图 13 GridView 的 Edit 列

即使您对 SQL 的操作仅限于定义命令结构 — 只定义语句而让控件来完成其他操作,也无需使用 ADO.NET 或担心如何使用命令或连接。想在用户单击 Update 时保留更改,可编写以下代码:
程序代码 程序代码
<asp:sqldatasource runat="server" id="MySource"
   connectionstring="SERVER=…;DATABASE=northwind;Integrated
   Security=SSPI;"
   updatecommand="Update employees SET
           firstname=@firstname, lastname=@lastname
           Where employeeid=@employeeid">
</asp:sqldatasource>
<asp:gridview runat="server" id="MyGridView"
   DataSourceId="MySource"
   DataKeyNames="employeeid" AutoGenerateEditButton="true">
   •••
</asp:gridview>
数据源的 UpdateCommand 属性被设置为 GridView 使用的 SQL 命令。您能够使用所需的任意数量的参数。如果您采用一种特殊的命名规则,参数值也能够自动解析。代表更新字段的参数(例如 firstname)必须与网格列的 DataField 属性名相匹配。用于标识工作记录的 Where 子句中使用的参数必须与 DataKeyNames 属性匹配,后者是显示记录的关键字段。最后,考虑这种情况:如果没有定义 UpdateCommand,却提交更改,那么 CanUpdate 返回值为假,并引发一个异常。RowUpdated 事件发出信号通知更新命令结束。通过更新命令更新的行数可在 RowUpdated 事件参数的 AffectedRows 属性中检索。
GridView 自动收集输入字段的值,填充 name/value 对词典,这个词典指示了每个行字段的新值。GridView 也公开一个 RowUpdating 事件,允许您修改正在传递到数据源对象的值。此外,在相关数据源上激发 Update 操作前,GridView 将自动调用 Page.IsValid。如果 Page.IsValid 返回值为假,将取消操作。这对使用包括验证程序在内的自定义编辑模板特别有用。
行删除操作方式与此相似。下面的 SQL 命令是一个数据源对象的 DeleteCommand 属性的合法内容:
Delete employees Whereemployeeid=@employeeid请注意,如果由于特定于数据库的约束而无法删除记录,删除操作将失败。例如,如果子记录通过某种关系引用父记录,父记录将无法删除。在这种情况下,引发一个异常。
GridView 控件不自动支持向数据源插入数据。没有这项功能完全是由于实现 GridView 不依赖于底层数据源的功能和特性。实际上,数据源对象提供一个 CanInsert 属性并支持一个 InsertCommand 属性。请注意,通过 GridView 和 DetailsView 控件的组合能够实现这个功能,一会您就会了解到。

DetailsView 控件
许多应用程序需要一次作用于一条记录。在 ASP.NET 1.x 中,没有内置的功能支持这种情况。创建单条记录视图是可能的,但需要您自己编写代码。首先,您需要获取记录,然后,将字段绑定到数据绑定表单,选择性地提供分页按钮来浏览记录。我编写了三个 Cutting Edge 列的安装程序来解决这个问题 — 2002 年 4 月、5 月和 6 月。
当生成主/详细视图时,经常需要显示单条记录的内容。通常,用户从网格中选择一条主记录,让应用程序追溯所有可用字段。通过组合 GridView 和 DetailsView,编写少量代码,就能够生成有层次结构的视图。
DetailsView 控件能够自动绑定到任何数据源控件,使用其数据操作集。控件能够自动分页、更新、插入和删除底层数据源的数据项,只要数据源支持这些操作。多数情况下,建立这些操作无需编写代码,如下所示:

程序代码 程序代码
<asp:detailsview runat="server" id="det"
   datasourceid="MySource"
   autogenerateeditbutton="true"
   autogenerateinsertbutton="true"
   autogeneratedeletebutton="true"
   allowpaging="true"
   headertext="Employees">
   <pagersettings mode="NextPreviousFirstLast"
      firstpageimageurl="images/first.gif"
      lastpageimageurl="images/last.gif"
      nextpageimageurl="images/next.gif"
      previouspageimageurl="images/prev.gif" />
</asp:detailsview>

DetailsView 控件的用户界面能够通过使用数据字段和类型进行自定义,其方式与 GridView 相似。DetailsView 不支持自定义模板,因为这项特殊的功能完全构造在新的 FormView 控件中。DetailsView 具有一个命令栏,显示 Edit、Delete 和 New 按钮的任意组合。当您单击 Edit 或 New 时,控件显示 Edit 或 Insert 模式,字段内容显示在文本框中。工作模式能通过 Mode 和 DefaultMode 属性控制。
使用 DetailsView 控件能很好地实现无需代码的主/详细视图。除了 Edit 和 Delete 按钮,GridView 控件支持 Select 按钮,它也是预定义的。通过设置 AutoGenerateSelectButton 属性为真,您能为每一行启用此按钮。当用户单击此按钮时,当前行输入选定状态,为 GridView 的 SelectedIndex 属性分配从 0 开始的索引值。此外,GridView 控件引发 SelectedIndexChanged 事件。应用程序可以挂钩到这个事件,并执行自定义代码。
在 ASP.NET 2.0 中,如果您想生成主/详细视图,则无需处理 SelectedIndexChanged 事件。您可以将一个 GridView 控件和一个 DetailsView 控件拖放到页面上,将两者绑定到一个数据源。生成无代码的主/详细视图的技巧是,将详细视图控件绑定到当前选定记录所代表的数据源,如下所示:
程序代码 程序代码
<asp:sqldatasource runat="server" id="MyDetailSource"    
   •••
   selectcommand="Select * FROM customers"
   filtere­xpression="customerid='@customerid'">
   <filterparameters>
     <asp:ControlParameter Name="customerid"
        ControlId="masterGrid"
        PropertyName="SelectedValue" />
   </filterparameters>
</asp:sqldatasource>


数据源对象的 FilterExpression 属性为 SelectCommand 指定的基础查询定义 Where 子句。参数值能够以多种方式指定,包括直接绑定一个控件属性。 对象将 @customerid 参数设置为主网格控件的 SelectedValue 属性存储的值。图 14 的代码显示如何配置主网格控件和详细视图控件。图 15 显示活动页面。请注意,无需程序代码来完成这些功能。

图 15 活动主网格

FormView 控件
FormView 是新的数据绑定控件,使用起来像是 DetailsView 的模板化版本。它每次从相关数据源中选择一条记录显示,选择性地提供分页按钮,用于在记录之间移动。与 DetailsView 控件不同的是,FormView 不使用数据控件字段,而是允许用户通过模板定义每个项目的显示。FormView 支持其数据源提供的任何基本操作。
FormView 控件是作为通常使用的更新和插入接口而设计的,它不能验证数据源架构,不支持高级编辑功能,比如外键字段下拉。然而,使用模板来提供此功能很容易。FormView 和 DetailsView 有两方面的功能差异。首先,FormView 控件具有 ItemTemplate、EditItemTemplate 和 InsertItemTemplate 属性,而 DetailsView 一个也没有。其次,FormView 缺少命令行 — 将可用功能进行分组的工具栏。与 GridView 和 DetailsView 控件不同的是,FormView 没有其自己默认的显示布局。同时,它的图形化布局完全是通过模板自定义的。因此,每个模板都包括特定记录需要的所有命令按钮。下列代码片断是在页面中嵌入一个 FormView 的典型写法。
程序代码 程序代码
<asp:FormView ID="EmpDetails" runat="server"
    DataSourceId="MySource" AllowPaging="true">
    <ItemTemplate>
      •••
    </ItemTemplate>
    <EditItemTemplate>
      •••
    </EditItemTemplate>
    <InsertItemTemplate>
      •••
    </InsertItemTemplate>
</asp:FormView>

图 16 说明一个使用 FormView 控件的页面。Edit 按钮通过命令名 Edit 的 asp:Button> 元素来添加。这将导致 FormView 从只读模式转换到编辑模式,使用定义过的 EditItemTemplate 显示。New 命令名将强制控件转换为插入模式,显示 InsertItemTemplate 的定义内容。最后,如果您将命令名为 Delete 的按钮添加到项目模板中,用户单击它时,FormView 将调用数据源的 Delete 命令。

图 16 FormView 控件

如何检索数据来更新或插入一条记录?您可以使用一个新的数据绑定关键字 Bind,它是专门为双向绑定而设计的:
Bind 关键字像 Eval 一样用于显示数据,而且能在更新或插入一条记录时检索输入值。此外,Bind 对 GridView 和 DetailsView 使用的 TemplateFields 非常有用。
Bind 将绑定控件属性值存入一个值集合,FormView 控件自动检索和使用这个集合来组合插入或编辑命令的参数列表。传递到 Bind 的参数必须与数据容器的字段名匹配。例如,上一个代码片断中的文本框存放备注字段的值。最后,还要记住的是编辑和插入模板必须包含保存变更的按钮。这是指普通的按钮 — 用于保存的 Update 和 Insert 以及用于放弃操作的 Cancel。
FormView 事件的工作方式与 DetailsView 和 GridView 相同。因此,如果想处理像数据预处理或后处理(例如,填充下拉框)这样更复杂的操作,您应该为 ItemCommand、ItemInserting 和 ModeChanging 之类的事件编写适当的事件处理程序。

小结
数据绑定控件是大多数 Web 应用程序的必要组成部分。数据绑定控件应该简单但功能强大。理想的情况是,它们应该以很少的单击操作以及有限的代码数量提供高级的功能。虽然 ASP.NET 2.0 仍然在使用,但是其新一代的数据绑定控件满足了这个需求。ASP.NET 1.x 数据绑定的主要缺点是需要为普通数据操作编写过多的代码。这一点已经随着数据源对象和 GridView 控件的引入而解决了。DetailsView 和 FormView 是对 GridView 的完美补充,代表了对 ASP.NET 1.x 数据工具箱的重大改进。

DetailsView  DataGrid   ImageField
(.Net企业开发)patterns & practices 企业程序库
(.Net企业开发)企业程序库(一)——缓存应用程序块简介
(.Net企业开发)企业程序库(二)——配置应用程序块简介
(.Net企业开发)企业程序库(三)——数据访问应用程序块
(.Net企业开发)企业程序库(四)——加密应用程序块简介
(.Net企业开发)之企业程序库(五)——异常处理应用程序块简介
(.Net企业开发)之企业程序库(六)——日志和规范应用程序块简介
(.Net企业开发)之企业程序库(七)——安全应用程序块
ASP.NET 2.0中的DataSource控件
使用ASP.NET 2.0中的GridView控件
在ASP.NET 2.0中使用页面导航控件
详细研究Asp.Net中的DataReader(附代码)
Asp.Net中使用DataReader对象
ASP.NET 数据访问类 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值