1、简化代码隐藏模型
ASP.NET 2.0 为代码隐藏页引入了一个改进的运行库,该库可简化页和代码之间的连接。在这一新的代码隐藏模型中,页被声明为分部类,这使得页和代码文件可在运行时编译为一个类。通过在 Inherits 属性中指定类名,页代码使用 <%@ Page %> 指令的 CodeFile 属性来引用代码隐藏文件。请注意,代码隐藏类的成员必须是公共或受保护的成员(不能为私有成员)。
与以前版本相比,这种简化的代码隐藏模型的好处在于无需维护代码隐藏类中服务器控件变量的各个不同的声明。使用分部类(2.0 中的新增功能)可在代码隐藏文件中直接访问 ASPX 页的服务器控件 ID。这极大地简化了代码隐藏页的维护工作。
CodeBehind_cs.aspx
<%@ page language="C#" CodeFile="CodeBehind_cs.aspx.cs" Inherits="CodeBehind_cs_aspx" %>
<html>
<head>
<title>ASP.NET CodeBehind Pages</title>
</head>
<body>
<form runat="server">
<h1>Welcome to ASP.NET 2.0!</h1>
<b>Enter Your Name:</b>
<asp:TextBox ID="TextBox1" Runat="server"/>
<asp:Button ID="Button1" Text="Click Me" OnClick="Button1_Click" Runat="server"/>
<br />
<br />
<asp:Label ID="Label1" Text="Hello" Runat="server" />
</form>
</body>
</html>
using System;
public partial class CodeBehind_cs_aspx : System.Web.UI.Page
{
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = "Hello " + TextBox1.Text;
}
}
在页之间共享代码
尽管可以将代码放在站点的每个页上(使用上一节中所述的内联或代码隐藏分离模型),但有时您将希望在站点中的多个页之间共享代码。将这些代码复制到需要它们的每个页上,这种做法既低效又使代码难以维护。幸运的是,ASP.NET 提供了几种简单的方法,使应用程序中的所有页都可以访问代码。
代码目录 与页可在运行时动态编译一样,任意代码文件(例如,.cs 或 .vb 文件)也可以在运行时动态编译。ASP.NET 2.0 引入了 App_Code 目录,该目录可以包含一些独立文件,这些文件包含要在应用程序中的多个页之间共享的代码。与 ASP.NET 1.x 不同(1.x 需要将这些文件预编译到 Bin 目录),App_Code 目录中的所有代码文件都将在运行时动态编译,然后提供给应用程序。可以在 App_Code 目录下放置多种语言的文件,前提是将这些文件划分到各子目录中(在 Web.config 中用特定语言注册这些子目录)。下面的示例演示如何使用 App_Code 目录包含一个从页调用的类文件。
源码目录结构:
CodeFolder_cs
|
|--------------App_Code
| |
| |--------------CustomClass.cs
|
|--------------CodeFolder_cs.aspx
CodeFolder_cs.aspx
<%@ page language="C#" %>
<script runat="server">
void Button1_Click(object sender, EventArgs e)
{
CustomClass c = new CustomClass();
Label1.Text = c.GetMessage(TextBox1.Text);
}
</script>
<html>
<head>
<title>ASP.NET Inline Pages</title>
</head>
<body>
<form id="Form1" runat="server">
<h1>Welcome to ASP.NET 2.0!</h1>
<b>Enter Your Name:</b>
<asp:TextBox ID="TextBox1" Runat="server"/>
<asp:Button ID="Button1" Text="Click Me" OnClick="Button1_Click" Runat="server"/>
<br />
<br />
<asp:Label ID="Label1" Text="Hello" Runat="server" />
</form>
</body>
</html>
CustomClass.cs
using System;
public class CustomClass
{
public String GetMessage(String input) {
return "Hello " + input;
}
}
默认情况下,App_Code 目录只能包含同一种语言的文件。但可以将 App_Code 目录划分为若干子目录(每个子目录包含同一语言的文件)以便可以在 App_Code 目录下包含多种语言。为此,需要在应用程序的 Web.config 文件中注册每个子目录。 <configuration>
<system.web>
<compilation>
<codeSubDirectories>
<add directoryName="Subdirectory"/>
</codeSubDirectories>
</compilation>
</system.web>
</configuration>
下面的示例演示了一个经过划分以包含 VB 和 C# 语言文件的 App_Code 目录。
源码目录结构:
CodeFolder_cs
|
|--------------App_Code
| |
| |--------------Subdirectory
| | |--------------CustomClass.vb
| |
| |--------------CustomClass.cs
|
|--------------CodeFolder2_cs.aspx
CodeFolder2_cs.aspx
<%@ page language="C#" %>
<script runat="server">
void Button1_Click(object sender, EventArgs e)
{
CustomClass c = new CustomClass();
Label1.Text = c.GetMessage(TextBox1.Text);
CustomClass2 c2 = new CustomClass2();
Label2.Text = c2.GetMessage(TextBox1.Text);
}
</script>
<html>
<head>
<title>ASP.NET Inline Pages</title>
</head>
<body>
<form id="Form1" runat="server">
<h1>Welcome to ASP.NET 2.0!</h1>
<b>Enter Your Name:</b>
<asp:TextBox ID="TextBox1" Runat="server"/>
<asp:Button ID="Button1" Text="Click Me" OnClick="Button1_Click" Runat="server"/>
<br />
<br />
<asp:Label ID="Label1" Runat="server" />
<br />
<asp:Label ID="Label2" Runat="server" />
</form>
</body>
</html>
CustomClass.cs
using System;
public class CustomClass
{
public String GetMessage(String input) {
return "Hello " + input;
}
}
Imports Microsoft.VisualBasic
Public Class CustomClass2
Public Function GetMessage(ByVal name As String) As String
Return "Hello from VB " & name
End Function
End Class
Bin 目录
在 ASP.NET 版本 1 中支持 Bin 目录,该目录类似于 Code 目录,不同的是它可以包含预编译的程序集。如果需要使用可能由其他人编写的代码,则此目录十分有用,您无需访问源代码(VB 或 C# 文件)就可以得到编译后的 DLL。只需将程序集放在 Bin 目录中,就可以在您的站点中使用它。默认情况下,Bin 目录中的所有程序集都自动加载到应用程序中,然后可供各页访问。您可能需要使用页最上方的 @Import 指令从 Bin 目录的程序集中导入特定的命名空间。 <@ Import Namespace="MyCustomNamespace" >
全局程序集缓存
.NET Framework 2.0 提供了表示 Framework 的各个部件的大量程序集。这些程序集存储在全局程序集缓存中,该缓存是程序集的版本化存储库,可供计算机上的所有应用程序使用(而不像 Bin 和 App_Code 那样仅限于特定的应用程序)。Framework 中的多个程序集都可自动提供给 ASP.NET 应用程序。通过在应用程序的 Web.config 文件中注册,可以注册更多的程序集。 <configuration>
<compilation>
<assemblies>
<add assembly="System.Data, Version=1.0.2411.0,
Culture=neutral,
PublicKeyToken=b77a5c561934e089"/>
</assemblies>
</compilation>
</configuration>
请注意,您仍需使用 @Import 指令使这些程序集中的命名空间可供各页使用。
4、数据源控件
ASP.NET 2.0 引入了声明性数据源控件,这些控件向页上的数据绑定 UI 控件公开来自后端存储(例如 SQL 数据库、中间层业务对象或 XML 文件)的数据。数据源控件还公开诸如排序、分页、缓存、更新、插入和删除数据等功能,UI 控件能够自动利用这些功能而无需代码。
数据源控件没有呈现形式,而是表示特定的后端数据存储,例如数据库、业务对象、XML 文件或 XML Web services。数据源控件还支持针对数据的丰富功能(例如排序、分页、筛选、更新、删除和插入),数据绑定 UI 控件能够自动使用这些功能。ASP.NET 包括以下现成的服务器控件:
SqlDataSource 支持绑定到 ADO.NET 提供程序(例如 Microsoft? SQL Server、OLEDB、ODBC 或 Oracle。)表示的 SQL 数据库。
ObjectDataSource 支持绑定到中间层对象,例如数据访问层或业务组件。
AccessDataSource 支持绑定到 Microsoft? Access (Jet) 数据库。
SiteMapDataSource 支持绑定到 ASP.NET 2.0 站点导航提供程序公开的层次结构。
XmlDataSource 支持绑定到 XML 文件或文档。
要在 Web 应用程序中显示的最常见数据类型之一是来自诸如 Microsoft SQL Server、Oracle 等 SQL 数据库或其他 OLEDB 或 ODBC 数据存储区的数据。SqlDataSource 控件在 Web 应用程序中表示到数据库的直接连接,数据绑定控件可使用它自动检索数据。SqlDataSource 旨在替代通常在页中编写以创建连接和命令来查询数据库的 ADO.NET 代码。由于数据查询被直接指定为数据源控件的属性,这有时称为两层模型,因为数据查询仍然在页代码中维护。由于这个原因,SqlDataSource 控件通常针对不需要完全封装的数据中间层对象的小型业余爱好者或个人站点。本教程后面有一个部分将讨论 ObjectDataSource 控件,该控件针对需要数据库查询的中间层封装的较大型企业。
数据绑定控件
除 ASP.NET 1.x 版中的数据绑定控件外,ASP.NET 还包括诸如 GridView、DetailsView、FormView、TreeView 和 Menu 等新的数据绑定 UI 控件,可以自定义这些控件以各种格式显示数据。GridView、DetailsView 和 FormView 控件还能自动利用数据源功能,使得向数据驱动页添加排序、分页和更新操作非常容易。
数据绑定控件是将数据作为标记向发出请求的客户端设备或浏览器呈现的 UI 控件。数据绑定控件能够自动绑定到从数据源公开的数据,并在页请求生命周期中的适当时间获取数据。这些控件还可以选择利用数据源功能,例如排序、分页、筛选、更新、删除和插入。数据绑定控件通过其 DataSourceID 属性连接到数据源控件。您可能熟悉 ASP.NET 1.x 版中的一些数据绑定控件,例如 DataGrid、DataList、Repeater 和诸如 DropDownList 这样的列表控件。ASP.NET 2.0 还包含几个新的数据绑定控件,例如:
GridView 以网格格式呈现数据。此控件是 DataGrid 控件的演变形式,并且能够自动利用数据源功能。
DetailsView 在标签/值对的表格中呈现单个数据项,此控件也能自动利用数据源功能。
FormView 在由自定义模板定义的窗体中一次呈现单个数据项。在标签/值对的表格中呈现单个数据项,此控件也能自动利用数据源功能。
TreeView 在可展开的节点的分层树视图中呈现数据。
Menu 在分层动态菜单(包括弹出式菜单)中呈现数据。
如果熟悉 ASP.NET 1.x 版中的 DataGrid 控件,则 GridView 是其替代控件,并支持非常相似的对象模型。
GridView 控件支持以下功能:
绑定到数据源控件。
内置的排序功能。
内置的更新和删除功能。
内置的分页功能。
内置的行选择功能。
对 GridView 对象模型进行编程访问以动态设置属性和处理事件。
诸如 CheckBoxField 和 ImageField 等新的列类型。
用于超链接列的多个数据字段。
用于选择、更新和删除的多个数据键字段。
可通过主题和样式自定义的外观。
创建数据报表
下面的示例演示与 SqlDataSource 控件关联的 GridView 控件
<%@ Page Language="C#" %>
<html>
<head runat="server">
<title>GridView Bound to SqlDataSource</title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView ID="GridView1" DataSourceID="SqlDataSource1" runat="server" />
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
SelectCommand="SELECT [au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract] FROM [authors]"
ConnectionString="<%$ ConnectionStrings:Pubs %>" />
</form>
</body>
</html>
SqlDataSource 控件并不仅限于连接到 Microsoft™ SQL Server 数据库。它实际上能够连接到被配置为 System.Data.Common.DbProviderFactory 的任何托管 ADO.NET 提供程序。默认情况下,.NET Framework machine.config 中包括四个提供程序: <configuration>
<system.data>
<DbProviderFactories>
<add name="Odbc Data Provider" invariant="System.Data.Odbc" type="System.Data.Odbc.OdbcFactory, ..." />
<add name="OleDb Data Provider" invariant="System.Data.OleDb" type="System.Data.OleDb.OleDbFactory, ..." />
<add name="OracleClient Data Provider" invariant="System.Data.OracleClient" type="System.Data.OracleClient.OracleClientFactory, ..." />
<add name="SqlClient Data Provider" invariant="System.Data.SqlClient" type="System.Data.SqlClient.SqlClientFactory, ..." />
</DbProviderFactories>
</system.data>
</configuration>
SqlDataSource 的 ProviderName 属性可设置为任何有效提供程序工厂的固定名称(默认为 System.Data.SqlClient)。注意,如果更改提供程序名称,则需要确保 ConnectionString 和 SelectCommand 属性使用所选提供程序的正确语法。
下面的示例演示 GridView 的 Columns 集合中的 BoundField 和 CheckBoxField 对象的集合。可分配给此集合的其他字段类型包括 ImageField、HyperLinkField、CommandField、ButtonField 和 TemplateField。
绑定列
GridViewBoundFields_cs.aspx
<%@ Page Language="C#" %>
<html>
<head id="Head1" runat="server">
<title>GridView Bound Fields</title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView ID="GridView1" DataSourceID="SqlDataSource1" AutoGenerateColumns="False"
runat="server">
<Columns>
<asp:BoundField HeaderText="ID" DataField="au_id" ReadOnly="true" />
<asp:BoundField HeaderText="Last Name" DataField="au_lname" />
<asp:BoundField HeaderText="First Name" DataField="au_fname" />
<asp:BoundField HeaderText="Phone" DataField="phone" />
<asp:BoundField HeaderText="Address" DataField="address" />
<asp:BoundField HeaderText="City" DataField="city" />
<asp:BoundField HeaderText="State" DataField="state" />
<asp:BoundField HeaderText="Zip Code" DataField="zip" />
<asp:CheckBoxField HeaderText="Contract" DataField="contract" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
SelectCommand="SELECT [au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract] FROM [authors]"
ConnectionString="<%$ ConnectionStrings:Pubs %>" />
</form>
</body>
</html>
使用存储过程
GridViewStoredProc_cs.aspx
<%@ Page Language="C#" %>
<html>
<head runat="server">
<title>GridView Bound to Stored Procedure</title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView ID="GridView1" DataSourceID="SqlDataSource1" AutoGenerateColumns="False"
runat="server">
<Columns>
<asp:BoundField DataField="TenMostExpensiveProducts" HeaderText="Product" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}" HeaderText="Price" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" SelectCommand="Ten Most Expensive Products"
ConnectionString="<%$ ConnectionStrings:Northwind %>" SelectCommandType="StoredProcedure" />
</form>
</body>
</html>
切换DATASOURCE控件模式
默认情况下,SqlDataSource 控件返回包含查询结果的 DataSet 对象中的 DataView。通过将 SqlDataSourceMode 属性设置为“DataReader”,可以配置 SqlDataSource 控件将数据作为 DataReader 返回。当只需对数据进行仅向前、只读访问时,使用 DataReader 一般比使用 DataSet 具有更好的性能。但是要注意 SqlDataSource 的排序功能在此模式下将被禁用。下面的示例演示 SqlDataSource 的 DataReader 模式。
<%@ Page Language="C#" %>
<html>
<head runat="server">
<title>GridView Bound to SqlDataReader</title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView ID="GridView1" DataSourceID="SqlDataSource1" AutoGenerateColumns="False"
runat="server">
<Columns>
<asp:BoundField DataField="TenMostExpensiveProducts" HeaderText="Product" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}" HeaderText="Price" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:Northwind %>"
SelectCommand="Ten Most Expensive Products"
SelectCommandType="StoredProcedure"
DataSourceMode="DataReader" />
</form>
</body>
</html>
在上面的示例中,SqlDataSource 使用 ASP.NET 2.0 中在运行时解析为连接字符串值的新的声明性表达式语法,按名称引用数据库连接字符串。连接字符串本身存储在 Web.config 文件中的 <connectionStrings> 配置节下面,以便易于在单个位置为应用程序中的所有页维护它。 <configuration>
<connectionStrings>
<add name="Pubs" connectionString="Server=(local);Integrated Security=True;Database=pubs;"
providerName="System.Data.SqlClient" />
</connectionStrings>
</configuration>
对配置节进行加密某些配置节可能包含诸如用户名和密码之类的敏感数据。虽然 ASP.NET 将 IIS 配置为防止浏览器访问 web.config 文件,但是,始终不将此类数据以明文形式存储在配置文件中仍是一种好的做法。ASP.NET 2.0 现在允许您对配置文件的单个节进行加密,这样,几乎不可能使用文本编辑器来读取这些配置节。
ASP.NET 包括两个内置的受保护配置提供程序:RSA 和 DPAPI DPAPI 提供程序使用特定于计算机的密钥,因此您必须在每台计算机上实际加密配置设置。默认使用的 RSA 提供程序允许您选择创建 RSA 密钥并将其安装在其他计算机上,这样您就可以在这些计算机之间复制相同的配置文件。此外,您还可以安装其他受保护配置提供程序供系统使用。
调用配置管理 API 可透明地使用加密的节,因为该 API 自动处理加密和解密。若要通过编程方式将配置节设置为加密的,可获取 ConfigurationSection.SectionInformation 属性,然后传入您选择的保护提供程序调用 ProtectSection 方法。若要使用默认提供程序,可以传入 null 或空字符串。UnprotectSection 方法禁用配置节的加密。
Current XML (decrypted):
<appSettings>
<add key="currencyService" value="
' target=_blank>http://www.microsoft.com/services/cu ... asmx" /> <add key="creditCardValidationService" value="
' target=_blank>http://www.microsoft.com/services/cc.asmx" /></appSettings>
Encrypted contents:
<appSettings configProtectionProvider="DataProtectionConfigurationProvider">
<EncryptedData>
<CipherData>
<CipherValue>AQAAANCMnd8BFdERjHoAwE/Cl+sBAAAA1NhEcJCaa0eWM9wd6RqsMAQAAAACAAAAAAADZgAAqAAAABAAAAB7Zg7Oo7zwLePUDRpmQcqdAAAAAASAAACgAAAAEAAAAMgX1cWq/4RcLNZmuy3TTknIAQAAgBEizttlPuH9QzAALphiwzEX4WjjZgmiqwJM0y5rZdrA2eIlAiX5vp39ikLBITpgNEojASiVY8jbzhX24e2dBI5Gr0lU5F6n47XrOLmZt50XnHqrPVv8JOq9Z23sEs27eWoi+bJ5TpceVDuIpukrrGZ/XHS7+E3vC62AaPY/gZz4BWj7aBM+woyXDRTA00fu6YjkWvOMCROdCMft5aZdPPn5I4bP5i+SO4lA/3mWk1NhmuFTUDffRWgOodapUYxZCzbkgueTX1S7Al5UuCA1Ajr5zNMZ6NRvw9w/EhhVADZ+ulbMVWBdepYdFvl8/HIcYlfxxV0hBgN0YOWZ4h8l5vhwMYL+Xays/KabiG8QDuXSnX1gWDbGdcx0/PaZsxVZJ9X0GexJMFHRhttNU6LbGj9xanHCa/TZUDPAH3N/dh2GpbDDb4xn0x94Wa4Oi431g/I8HSW3E3m6yJEDcnGxJ5BZIjuHFiEn2ZnaacJ3LggqUBmbecxVI0OOqmHLnMjIgxyccboXmqu+TwPHrsasYZu5XMzFvT9Qrxy3Gii+mvQ0PNpTFu8B3uhi3e50B7qAczO0dQAydCSUICe6dlxvPGPkxwR/oGhGFAAAAEPY/rFa4QRwAID3VVadDW22s6RL</CipherValue>
</CipherData>
</EncryptedData>
</appSettings>
数据排序
SqlDataSource 控件在其 DataSourceMode 属性设置为“DataSet”时支持排序。若要在 GridView 中启用排序 UI,请将 AllowSorting 属性设置为 true。这导致 GridView 呈现其列标题的链接按钮,可单击这些按钮对列进行排序。GridView 控件将与列字段关联的 SortExpression 传递给数据源控件,后者向 GridView 返回排序的数据。
SqlDataSource 预期的 SortExpression 语法与 System.Data.DataView 的 Sort 属性的语法相同,虽然其他数据源可能支持不同的语法。由于 SqlDataSource 的排序行为依赖基础的 DataView Sort 属性,SqlDataSource 仅在 DataSet 模式下支持排序;如果设置为 DataReader 模式,则排序将被禁用。SortExpression 通常被设置为与 GridView 的某列关联的单个字段名称。GridView 在每次单击时自动交替向 SortExpression 追加“ASC”或“DESC”,以便在升序和降序排序顺序之间切换。
<%@ Page Language="C#" %>
<html>
<head id="Head1" runat="server">
<title>Sorting Data Using GridView</title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView ID="GridView1" AllowSorting="true" runat="server" DataSourceID="SqlDataSource1"
AutoGenerateColumns="False">
<Columns>
<asp:BoundField HeaderText="ID" DataField="au_id" SortExpression="au_id" />
<asp:BoundField HeaderText="Last Name" DataField="au_lname" SortExpression="au_lname" />
<asp:BoundField HeaderText="First Name" DataField="au_fname" SortExpression="au_fname" />
<asp:BoundField HeaderText="Phone" DataField="phone" SortExpression="phone" />
<asp:BoundField HeaderText="Address" DataField="address" SortExpression="address" />
<asp:BoundField HeaderText="City" DataField="city" SortExpression="city" />
<asp:BoundField HeaderText="State" DataField="state" SortExpression="state" />
<asp:BoundField HeaderText="Zip Code" DataField="zip" SortExpression="zip" />
<asp:CheckBoxField HeaderText="Contract" SortExpression="contract" DataField="contract" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
SelectCommand="SELECT [au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract] FROM [authors]"
ConnectionString="<%$ ConnectionStrings:Pubs %>" />
</form>
</body>
</html>
数据分页通过将 AllowPaging 属性设置为 true,还可以在 GridView 中启用分页 UI。GridView 能够对从数据源返回的任何支持 ICollection 接口的值自动进行分页。当 SqlDataSource 处于 DataSet 模式时返回的 DataView 支持此接口,因此 GridView 能够对结果分页。当处于 DataReader 模式时,GridView 不能对 SqlDataSource 返回的数据分页。下面的示例基于 DataSet 模式下的 SqlDataSource 演示了 GridView 分页 UI。
<%@ Page Language="C#" %>
<html>
<head id="Head1" runat="server">
<title>Paging Data Using GridView</title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView ID="GridView1" AllowSorting="true" AllowPaging="true" runat="server" DataSourceID="SqlDataSource1"
AutoGenerateColumns="False">
<Columns>
<asp:BoundField HeaderText="ID" DataField="au_id" SortExpression="au_id" />
<asp:BoundField HeaderText="Last Name" DataField="au_lname" SortExpression="au_lname" />
<asp:BoundField HeaderText="First Name" DataField="au_fname" SortExpression="au_fname" />
<asp:BoundField HeaderText="Phone" DataField="phone" SortExpression="phone" />
<asp:BoundField HeaderText="Address" DataField="address" SortExpression="address" />
<asp:BoundField HeaderText="City" DataField="city" SortExpression="city" />
<asp:BoundField HeaderText="State" DataField="state" SortExpression="state" />
<asp:BoundField HeaderText="Zip Code" DataField="zip" SortExpression="zip" />
<asp:CheckBoxField HeaderText="Contract" SortExpression="contract" DataField="contract" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
SelectCommand="SELECT [au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract] FROM [authors]"
ConnectionString="<%$ ConnectionStrings:Pubs %>" />
</form>
</body>
</html>
<%@ Page Language="C#" %>
<html>
<head id="Head1" runat="server">
<title>Pager Settings and Styles</title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView ID="GridView1" AllowSorting="true" AllowPaging="true" PageSize="3" runat="server"
DataSourceID="SqlDataSource1" AutoGenerateColumns="False">
<PagerSettings Mode="NextPreviousFirstLast" Position="TopAndBottom" FirstPageImageUrl="~/Images/First.gif"
LastPageImageUrl="~/Images/Last.gif" NextPageImageUrl="~/Images/Next.gif" PreviousPageImageUrl="~/Images/Prev.gif" />
<PagerStyle ForeColor="White" HorizontalAlign="Right" BackColor="#284775" />
<Columns>
<asp:BoundField HeaderText="ID" DataField="au_id" SortExpression="au_id" />
<asp:BoundField HeaderText="Last Name" DataField="au_lname" SortExpression="au_lname" />
<asp:BoundField HeaderText="First Name" DataField="au_fname" SortExpression="au_fname" />
<asp:BoundField HeaderText="Phone" DataField="phone" SortExpression="phone" />
<asp:BoundField HeaderText="Address" DataField="address" SortExpression="address" />
<asp:BoundField HeaderText="City" DataField="city" SortExpression="city" />
<asp:BoundField HeaderText="State" DataField="state" SortExpression="state" />
<asp:BoundField HeaderText="Zip Code" DataField="zip" SortExpression="zip" />
<asp:CheckBoxField HeaderText="Contract" SortExpression="contract" DataField="contract" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" SelectCommand="SELECT [au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract] FROM [authors]"
ConnectionString="<%$ ConnectionStrings:Pubs %>" />
</form>
</body>
</html>
上面的示例中的分页操作完全是由 GridView 控件对支持 ICollection 接口的 SqlDataSource 返回的 DataView 执行的。在此例中,GridView 从数据源检索所有数据记录,呈现行的一个子集,然后丢弃其余的行。这有时称为“UI 分页”,因为分页逻辑发生在 GridView 控件的呈现层中。虽然便于对任意集合分页,但这不一定是对数据分页的最有效方式。还可以在数据源接口级别配置分页,以便 GridView 仅从数据源请求呈现当前页所需要的行数。
SqlDataSource 控件目前不支持接口级别的分页。ObjectDataSource 控件支持此功能
更新和删除数据
在 GridView 中启用用于 Update 或 Delete 的 UI,可以将 AutoGenerateEditButton 和 AutoGenerateDeleteButton 属性设置为 true,或者可以向 GridView 控件添加一个 CommandField 并启用其 ShowEditButton 和 ShowDeleteButton 属性。GridView 支持一次编辑或删除一行。对于编辑,用户通过单击“Edit”(编辑)按钮将行置于编辑模式,然后在该行处于编辑模式时单击“Update”(更新)按钮确认 Update。用户还可以单击“Cancel”(取消)按钮中止编辑操作并返回只读模式。
<%@ Page Language="C#" %>
<html>
<head runat="server">
<title>Updating Data Using GridView</title>
</head>
<body>
<form id="form1" runat="server">
<asp:GridView ID="GridView1" AllowSorting="true" AllowPaging="true" Runat="server"
DataSourceID="SqlDataSource1" AutoGenerateEditButton="true" DataKeyNames="au_id"
AutoGenerateColumns="False">
<Columns>
<asp:BoundField ReadOnly="true" HeaderText="ID" DataField="au_id" SortExpression="au_id" />
<asp:BoundField HeaderText="Last Name" DataField="au_lname" SortExpression="au_lname" />
<asp:BoundField HeaderText="First Name" DataField="au_fname" SortExpression="au_fname" />
<asp:BoundField HeaderText="Phone" DataField="phone" SortExpression="phone" />
<asp:BoundField HeaderText="Address" DataField="address" SortExpression="address" />
<asp:BoundField HeaderText="City" DataField="city" SortExpression="city" />
<asp:BoundField HeaderText="State" DataField="state" SortExpression="state" />
<asp:BoundField HeaderText="Zip Code" DataField="zip" SortExpression="zip" />
<asp:CheckBoxField HeaderText="Contract" SortExpression="contract" DataField="contract" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" Runat="server" SelectCommand="SELECT [au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract] FROM [authors]"
UpdateCommand="UPDATE [authors] SET [au_lname] = @au_lname, [au_fname] = @au_fname, [phone] = @phone, [address] = @address, [city] = @city, [state] = @state, [zip] = @zip, [contract] = @contract WHERE [au_id] = @au_id"
ConnectionString="<%$ ConnectionStrings:Pubs %>" />
</form>
</body>
</html>
在 Update 和 Delete 操作中扮演特殊角色的一个重要属性是 DataKeyNames 属性。此属性通常被设置为数据源中字段的名称,这些字段是用于匹配该数据源中的给定行的主键的一部分。
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:Pubs %>"
SelectCommand="SELECT [au_id], [au_lname], [au_fname], [state] FROM [authors]"
UpdateCommand="UPDATE [authors] SET [au_id] = @au_id, [au_lname] = @au_lname, [au_fname] = @au_fname, [state] = @state WHERE [au_id] = @original_au_id"
DeleteCommand="DELETE FROM [authors] WHERE [au_id] = @original_au_id"/>
OldValuesParameterFormatString="original_{0}"
筛选数据
数据驱动页中的一种常见方案是筛选报表中的数据的能力。例如,假设用户可以从 DropDownList 中的一组字段值中选择以筛选报表网格,从而仅显示具有匹配字段值的行。在 ASP.NET 1.x 版中,将需要在代码中执行以下步骤:
1. 如果请求是回发,则在 Page_Load 中取消数据绑定
2. 处理 SelectedIndexChanged 事件
3. 向命令的 Parameters 集合添加 DropDownList SelectedValue
4. 执行该命令并调用 DataBind
在 ASP.NET 2.0 中,由于使用了声明性“数据参数”对象,因此不再使用此代码。数据参数允许将外部值以声明方式与数据源操作关联。这些参数通常与命令表达式或属性中的变量关联,例如 SQL 语句中的参数或 SqlDataSource 的存储过程。数据源控件公开参数集合属性,这些属性可以包含每个受支持的数据操作的参数对象。例如:
<asp:DropDownList ID="DropDownList1" ... runat="server"/>
...
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:Pubs %>"
SelectCommand="SELECT [au_id], [au_lname], [au_fname], [state] FROM [authors] WHERE [state] = @state">
<SelectParameters>
<asp:ControlParameter Name="state" ControlID="DropDownList1" PropertyName="SelectedValue" />
</SelectParameters>
</asp:SqlDataSource>
<asp:SqlDataSource ID="SqlDataSource1" Runat="server" SelectCommand="SELECT [au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract] FROM [authors] WHERE [state] = @state"
UpdateCommand="UPDATE [authors] SET [au_lname] = @au_lname, [au_fname] = @au_fname, [phone] = @phone, [address] = @address, [city] = @city, [state] = @state, [zip] = @zip, [contract] = @contract WHERE [au_id] = @au_id"
ConnectionString="<%$ ConnectionStrings:Pubs %>">
<SelectParameters>
<asp:QueryStringParameter Name="state" QueryStringField="state" DefaultValue="CA" />
</SelectParameters>
<UpdateParameters>
<asp:Parameter Name="au_lname" />
<asp:Parameter Name="au_fname" />
<asp:Parameter Name="phone" />
<asp:Parameter Name="address" />
<asp:Parameter Name="city" />
<asp:Parameter Name="state" />
<asp:Parameter Name="zip" />
<asp:Parameter Name="contract" />
<asp:Parameter Name="au_id" />
</UpdateParameters>
</asp:SqlDataSource>
可以配置数据参数以便从以下任意来源检索值:
Parameter Parameter 类是派生其他所有 Parameter 类型的公共基类。Parameter 类还作为静态参数的实现,其中值是使用 DefaultValue 属性静态指定的。
Parameter 共享一个公共的 Name 属性,该属性是特定数据源操作的参数名称(例如,这将匹配 SqlDataSource 的 SelectCommand 中的参数名称)。所有 Parameter 还共享一个 Type 属性,该属性指定参数值的类型。
Parameter 还共享一个 Direction 属性,该属性用于指定 Parameter 是用于 Input、Output(或 ReturnValue)还是同时用于 Input 和 Output。数据源一般从传递给数据源操作的状态事件的事件参数公开输出参数和返回值。
QueryStringParameter QueryStringParameter 类将 querystring 字段的值绑定到 Parameter 对象的值。QueryStringField 属性与从中检索值的 querystring 字段的名称相匹配。DefaultValue 属性将在 querystring 值不可用的任何时候返回。
ControlParameter ControlParameter 类将 Control 属性的值绑定到 Parameter 对象的值。ControlID 属性与其属性被绑定到该参数的 Control 的 ID 相匹配。PropertyName 指定从中检索实际值的控件的属性。由 ControlID 指定其 ID 的 Control 能够可选地定义 ControlValuePropertyAttribute,该属性确定要从中检索控件的值的默认属性名称。此属性将在未显式设置 PropertyName 的任何时候使用。ControlValuePropertyAttribute 应用于以下控件属性:
* Label.Text
* TextBox.Text
* ListControl.SelectedValue(例如 DropDownList)
* CheckBox.Checked
* Calendar.SelectedDate
* DetailsView.SelectedValue
* GridView.SelectedValue
* TreeView.SelectedValue
* FileUpload.FileBytes
SessionParameter SessionParameter 类将 Session 对象的值绑定到 Parameter 对象的值。SessionField 属性与从中检索值的 Session 键的名称相匹配。DefaultValue 属性将在 Session 值不可用的任何时候返回。
FormParameter FormParameter 类将 HTML 窗体字段的值绑定到 Parameter 对象的值。FormField 属性与从中检索值的窗体字段的名称相匹配。DefaultValue 属性将在 Form 值不可用的任何时候返回。
CookieParameter CookieParameter 类将 HttpCookie 的值绑定到 Parameter 对象的值。CookieName 属性与从中检索值的 Cookie 的名称相匹配(仅支持简单值 Cookie)。DefaultValue 属性将在 Cookie 值不可用的任何时候返回。
ProfileParameter ProfileParameter 类将 User Profile 对象的值绑定到 Parameter 对象的值。ParameterName 属性与从中检索值的配置文件属性的名称相匹配。DefaultValue 属性将在该属性值不可用的任何时候返回。
缓存数据
若要对 SqlDataSource 控件(以及稍后将讨论的 ObjectDataSource)启用缓存,请将 EnableCaching 属性设置为 true。可以使用 CacheDuration 属性指定要在缓存中存储项的时间长度(以秒为单位)。还可以将 CacheExpirationPolicy 属性设置为 Sliding 或 Absolute,就像能够从缓存 API 中所做的那样。当 DataSourceMode 属性设置为“DataSet”时,缓存仅在 SqlDataSource 控件上受支持。
例如,如果将 CacheDuration 设置为 5,将 SlidingExpiration 设置为 Absolute,SqlDataSource 将在第一次请求该页时从数据库检索数据,并将该数据存储在缓存中。对于后续的请求,SqlDataSource 将尝试检索缓存项以满足该请求而不返回到原始数据库。在 5 秒之后(如果缓存内存压力很高,或许会更早),该缓存项将被清除,对该页的后续请求将导致 SqlDataSource 再次返回数据库(使用新数据重复该缓存过程)。
如果将 CacheDuration 设置为 5,将 SlidingExpiration 设置为 Sliding,则只要数据源每 5 秒请求一次缓存的数据,缓存的数据就将定期刷新其生存时间。如果某个页至少每 5 秒请求一次缓存的数据,并且不存在缓存内存压力,则缓存的数据就会永远有效地保留在缓存中。另一方面,如果 5 秒钟时段内没有针对缓存的数据的请求,则缓存的项将被清除,在下一次出现请求时,SqlDataSource 控件将再次返回原始数据库。
<asp:SqlDataSource ID="SqlDataSource1" Runat="server" SelectCommand="SELECT DatePart(second, GetDate()) As TimeStamp, [au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract] FROM [authors] WHERE [state] = @state" ConnectionString="<%$ ConnectionStrings:Pubs %>" CacheDuration="5" EnableCaching="True">
<SelectParameters>
<asp:ControlParameter Name="state" ControlID="DropDownList1" />
</SelectParameters>
</asp:SqlDataSource>
一种很适合较小的数据查询的替代方法是最初从数据库选择所有数据放在缓存中,然后针对不同的参数值筛选单个缓存项。为了支持此方案,SqlDataSource 控件支持一个 FilterExpression 属性和对应的 FilterParameters 集合。与向命令本身应用参数值(SelectParameters 就是这样)不同,筛选表达式应用于通过执行该命令返回的 DataView 对象的 RowFilter 属性。该表达式语法必须与 DataView Row Filter 属性的预期语法匹配。
<asp:SqlDataSource ID="SqlDataSource1" runat="server"
ConnectionString="<%$ ConnectionStrings:Pubs %>"
SelectCommand="SELECT [au_id], [au_lname], [au_fname], [state] FROM [authors]">
FilterExpression="state = '{0}'"
<FilterParameters>
<asp:ControlParameter Name="state" ControlID="DropDownList1" PropertyName="SelectedValue" />
</FilterParameters>
</asp:SqlDataSource>
缓存数据始终是性能(不必在每次请求时返回数据库)和陈旧数据(因为缓存项包含在特定时间捕获的数据的快照)之间的权衡。页经常使用相对较低的 CacheDuration 值以确保缓存数据相当的新。更理想的情况是仅当数据库中的基础数据更改时才使缓存项失效。只要数据未更改,就没有理由清除缓存项。
ASP.NET 2.0 中的一个称为 SQL Cache Invalidation 的新功能允许配置数据源无限期地(或在指定的持续时间内)缓存数据,直至数据库中的数据更改,届时缓存项将被清除。此项技术允许使用更高的 CacheDuration 值,同时仍然保证显示的数据始终与数据库中的值匹配。SQL Cache Invalidation 仅在 Microsoft™ SQL Server 数据库上受支持。存在两种 SQL Cache Invalidation 实现:SQL Server 2005 上支持的基于通知的实现和早期版本的 SQL Server 上支持的基于轮询的实现。
<asp:SqlDataSource ID="SqlDataSource1" Runat="server" SelectCommand="SELECT DatePart(second, GetDate()) As TimeStamp, [au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract] FROM [authors]"
UpdateCommand="UPDATE [authors] SET [au_lname] = @au_lname, [au_fname] = @au_fname, [phone] = @phone, [address] = @address, [city] = @city, [state] = @state, [zip] = @zip, [contract] = @contract WHERE [au_id] = @au_id"
ConnectionString="<%$ ConnectionStrings:Pubs %>" EnableCaching="True" FilterExpression="state='{0}'" SqlCacheDependency="Pubs:Authors">
<UpdateParameters>
<asp:Parameter Name="au_lname" />
<asp:Parameter Name="au_fname" />
<asp:Parameter Name="phone" />
<asp:Parameter Name="address" />
<asp:Parameter Name="city" />
<asp:Parameter Name="state" />
<asp:Parameter Name="zip" />
<asp:Parameter Name="contract" />
<asp:Parameter Name="au_id" />
</UpdateParameters>
<FilterParameters>
<asp:ControlParameter ControlID="DropDownList1" Name="state" PropertyName="SelectedValue" />
</FilterParameters>
</asp:SqlDataSource>
主/详细信息和 DetailsView 控件
GridView 控件支持一个 SelectedValue 属性,该属性指示 GridView 中当前选择的行。SelectedValue 属性求值为 DataKeyNames 属性中指定的第一个字段的值。通过将 AutoGenerateSelectButton 设置为 true,或者通过向 GridView Columns 集合添加 ShowSelectButton 设置为 true 的 CommandField,可以启用用于 GridView 上的选择的 UI。然后 GridView 的 SelectedValue 属性可以与数据源中的 ControlParameter 关联以用于查询详细信息记录
<%@ Page Language="C#" %>
<html>
<head id="Head1" runat="server">
<title>GridView DetailsView Master-Details (1 Page)</title>
</head>
<body>
<form id="form1" runat="server">
<b>Choose a state:</b>
<asp:DropDownList ID="DropDownList1" DataSourceID="SqlDataSource2" AutoPostBack="true"
DataTextField="state" runat="server" />
<asp:SqlDataSource ID="SqlDataSource2" runat="server" SelectCommand="SELECT DISTINCT [state] FROM [authors]"
ConnectionString="<%$ ConnectionStrings:Pubs %>" />
<br />
<br />
<table>
<tr>
<td valign="top">
<asp:GridView ID="GridView1" AllowSorting="True" AllowPaging="True" runat="server"
DataSourceID="SqlDataSource1" DataKeyNames="au_id"
AutoGenerateColumns="False" Width="427px">
<Columns>
<asp:CommandField ShowSelectButton="True" />
<asp:BoundField DataField="au_id" HeaderText="au_id" ReadOnly="True" SortExpression="au_id" />
<asp:BoundField DataField="au_lname" HeaderText="au_lname" SortExpression="au_lname" />
<asp:BoundField DataField="au_fname" HeaderText="au_fname" SortExpression="au_fname" />
<asp:BoundField DataField="state" HeaderText="state" SortExpression="state" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" SelectCommand="SELECT [au_id], [au_lname], [au_fname], [state] FROM [authors] WHERE ([state] = @state)"
ConnectionString="<%$ ConnectionStrings:Pubs %>">
<SelectParameters>
<asp:ControlParameter ControlID="DropDownList1" Name="state" PropertyName="SelectedValue"
Type="String" />
</SelectParameters>
</asp:SqlDataSource>
</td>
<td valign="top">
<asp:DetailsView AutoGenerateRows="False" DataKeyNames="au_id" DataSourceID="SqlDataSource3"
HeaderText="Author Details" ID="DetailsView1" runat="server" Width="275px">
<Fields>
<asp:BoundField DataField="au_id" HeaderText="au_id" ReadOnly="True" SortExpression="au_id" />
<asp:BoundField DataField="au_lname" HeaderText="au_lname" SortExpression="au_lname" />
<asp:BoundField DataField="au_fname" HeaderText="au_fname" SortExpression="au_fname" />
<asp:BoundField DataField="phone" HeaderText="phone" SortExpression="phone" />
<asp:BoundField DataField="address" HeaderText="address" SortExpression="address" />
<asp:BoundField DataField="city" HeaderText="city" SortExpression="city" />
<asp:BoundField DataField="state" HeaderText="state" SortExpression="state" />
<asp:BoundField DataField="zip" HeaderText="zip" SortExpression="zip" />
<asp:CheckBoxField DataField="contract" HeaderText="contract" SortExpression="contract" />
</Fields>
</asp:DetailsView>
<asp:SqlDataSource ConnectionString="<%$ ConnectionStrings:Pubs %>" ID="SqlDataSource3"
runat="server" SelectCommand="SELECT [au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract] FROM [authors] WHERE ([au_id] = @au_id)">
<SelectParameters>
<asp:ControlParameter ControlID="GridView1" Name="au_id" PropertyName="SelectedValue"
Type="String" />
</SelectParameters>
</asp:SqlDataSource>
</td>
</tr>
</table>
<br />
</form>
</body>
</html>
DetailsView 像 GridView 一样支持编辑,您可以使用 AutoGenerateEditButton 或 CommandField.ShowEditButton 属性以同样的方式启用该 UI。当然,与 DetailsView 关联的数据源还必须配置为支持 Update 操作(这里通过在 SqlDataSource 上指定 UpdateCommand 实现)。
<%@ Page Language="C#" %>
<html>
<head id="Head1" runat="server">
<title>GridView DetailsView Master-Details (with Editing)</title>
</head>
<script runat="server">
protected void DetailsView1_ItemUpdated(Object sender, System.Web.UI.WebControls.DetailsViewUpdatedEventArgs e) {
GridView1.DataBind();
DropDownList1.DataBind();
}
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
DetailsView1.ChangeMode(DetailsViewMode.ReadOnly);
}
protected void GridView1_Sorted(object sender, EventArgs e)
{
DetailsView1.ChangeMode(DetailsViewMode.ReadOnly);
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
DetailsView1.ChangeMode(DetailsViewMode.ReadOnly);
}
protected void GridView1_PageIndexChanged(object sender, EventArgs e)
{
DetailsView1.ChangeMode(DetailsViewMode.ReadOnly);
}
</script>
<body>
<form id="form1" runat="server">
<b>Choose a state:</b>
<asp:DropDownList ID="DropDownList1" DataSourceID="SqlDataSource2" AutoPostBack="true"
DataTextField="state" runat="server" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged" />
<asp:SqlDataSource ID="SqlDataSource2" runat="server" SelectCommand="SELECT DISTINCT [state] FROM [authors]"
ConnectionString="<%$ ConnectionStrings:Pubs %>" />
<br />
<br />
<table>
<tr>
<td valign="top">
<asp:GridView ID="GridView1" AllowSorting="True" AllowPaging="True" runat="server"
DataSourceID="SqlDataSource1" DataKeyNames="au_id"
AutoGenerateColumns="False" Width="427px" OnSelectedIndexChanged="GridView1_SelectedIndexChanged" OnSorted="GridView1_Sorted" OnPageIndexChanged="GridView1_PageIndexChanged">
<Columns>
<asp:CommandField ShowSelectButton="True" />
<asp:BoundField DataField="au_id" HeaderText="au_id" ReadOnly="True" SortExpression="au_id" />
<asp:BoundField DataField="au_lname" HeaderText="au_lname" SortExpression="au_lname" />
<asp:BoundField DataField="au_fname" HeaderText="au_fname" SortExpression="au_fname" />
<asp:BoundField DataField="state" HeaderText="state" SortExpression="state" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" SelectCommand="SELECT [au_id], [au_lname], [au_fname], [state] FROM [authors] WHERE ([state] = @state)"
ConnectionString="<%$ ConnectionStrings:Pubs %>">
<SelectParameters>
<asp:ControlParameter ControlID="DropDownList1" Name="state" PropertyName="SelectedValue"
Type="String" />
</SelectParameters>
</asp:SqlDataSource>
</td>
<td valign="top">
<asp:DetailsView AutoGenerateRows="False" DataKeyNames="au_id" OnItemUpdated="DetailsView1_ItemUpdated" DataSourceID="SqlDataSource3"
HeaderText="Author Details" ID="DetailsView1" runat="server" Width="275px">
<Fields>
<asp:BoundField DataField="au_id" HeaderText="au_id" ReadOnly="True" SortExpression="au_id" />
<asp:BoundField DataField="au_lname" HeaderText="au_lname" SortExpression="au_lname" />
<asp:BoundField DataField="au_fname" HeaderText="au_fname" SortExpression="au_fname" />
<asp:BoundField DataField="phone" HeaderText="phone" SortExpression="phone" />
<asp:BoundField DataField="address" HeaderText="address" SortExpression="address" />
<asp:BoundField DataField="city" HeaderText="city" SortExpression="city" />
<asp:BoundField DataField="state" HeaderText="state" SortExpression="state" />
<asp:BoundField DataField="zip" HeaderText="zip" SortExpression="zip" />
<asp:CheckBoxField DataField="contract" HeaderText="contract" SortExpression="contract" />
<asp:CommandField ShowEditButton="True" />
</Fields>
</asp:DetailsView>
<asp:SqlDataSource ID="SqlDataSource3" runat="server" ConnectionString="<%$ ConnectionStrings:Pubs %>"
SelectCommand="SELECT [au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract] FROM [authors] WHERE ([au_id] = @au_id)"
UpdateCommand="UPDATE [authors] SET [au_lname] = @au_lname, [au_fname] = @au_fname, [phone] = @phone, [address] = @address, [city] = @city, [state] = @state, [zip] = @zip, [contract] = @contract WHERE [au_id] = @au_id">
<SelectParameters>
<asp:ControlParameter ControlID="GridView1" Name="au_id" PropertyName="SelectedValue"
Type="String" />
</SelectParameters>
<UpdateParameters>
<asp:Parameter Name="au_lname" Type="String" />
<asp:Parameter Name="au_fname" Type="String" />
<asp:Parameter Name="phone" Type="String" />
<asp:Parameter Name="address" Type="String" />
<asp:Parameter Name="city" Type="String" />
<asp:Parameter Name="state" Type="String" />
<asp:Parameter Name="zip" Type="String" />
<asp:Parameter Name="contract" Type="Boolean" />
<asp:Parameter Name="au_id" Type="String" />
</UpdateParameters>
</asp:SqlDataSource>
</td>
</tr>
</table>
<br />
</form>
</body>
</html>
每当数据源发生更改后(例如更新后),数据绑定控件通常都会自动重新绑定到其数据源。但是,在前面的示例中,DetailsView 绑定到 GridView 外的其他数据源,因此,当调用 Update 操作时,只有 DetailsView 会从其数据源接收更改事件。若要强制 GridView 在 DetailsView 执行更新时也进行重新绑定,可在 DetailsView ItemUpdated 事件中对 GridView 显式调用 DataBind()。此示例还处理事件,以在出现 GridView 排序或分页操作或在 DropDownList 控件中选择了新的筛选器值时禁用编辑。
在 Web 应用程序中将主/详细信息显示拆分到若干页上是很常见的。为此,可以向 GridView 的每一行添加超链接以导航到单独的详细信息页,并与 querystring 一起传递参数。在详细信息页中,绑定到 DetailsView 的数据源将使用 QueryStringParameter 对象接受这些参数。
可以通过向 GridView 的 Columns 集合添加 HyperLinkField 对象来添加超链接。HyperLinkField 的 Text 属性设置要为超链接显示的文本(例如“查看详细信息…”),而 NavigateUrl 属性则指定要在链接被单击时导航的 URL。不必为所有行指定静态 URL,更为普遍的是指定要在动态 URL 的构造中使用的 NavigateUrlFields。可以声明方式将 NavigateUrlFields 设置为数据源中的字段的逗号分隔的列表。NavigateUrlFormatString 属性指定用于 URL 的标准 .NET Framework 格式字符串,并使用像 {0} 和 {1} 这样的占位符在运行时替换字段值。
下一个示例通过在不同的页中使用 GridView 和 DetailsView 演示了一个主/详细信息方案。上一个示例演示绑定到相同类型的记录(作者)的 GridView 和 DetailsView,与上一个示例不同,此示例为主控件和详细信息控件显示不同类型的记录(作者和书籍),这些记录由基础表中的外键关系进行关联。因为一个作者记录可能具有多个关联的书籍,DetailsView 已被配置为支持对详细信息页中的书籍记录进行分页。
GridViewMasterDetailsPage_cs.aspx
<%@ Page Language="C#" %>
<html>
<head runat="server">
<title>GridView DetailsView Master-Details (2 Page)</title>
</head>
<body>
<form id="form1" runat="server">
<b>Choose a state:</b>
<asp:DropDownList ID="DropDownList1" DataSourceID="SqlDataSource2" AutoPostBack="true"
DataTextField="state" Runat="server" />
<asp:SqlDataSource ID="SqlDataSource2" Runat="server" SelectCommand="SELECT DISTINCT [state] FROM [authors]"
ConnectionString="<%$ ConnectionStrings:Pubs %>" />
<br />
<br />
<asp:GridView ID="GridView1" AllowSorting="True" AllowPaging="True" Runat="server"
DataSourceID="SqlDataSource1" DataKeyNames="au_id"
AutoGenerateColumns="False">
<Columns>
<asp:BoundField ReadOnly="true" HeaderText="ID" DataField="au_id" SortExpression="au_id" />
<asp:BoundField HeaderText="Last Name" DataField="au_lname" SortExpression="au_lname" />
<asp:BoundField HeaderText="First Name" DataField="au_fname" SortExpression="au_fname" />
<asp:BoundField HeaderText="Phone" DataField="phone" SortExpression="phone" />
<asp:BoundField HeaderText="Address" DataField="address" SortExpression="address" />
<asp:BoundField HeaderText="City" DataField="city" SortExpression="city" />
<asp:BoundField HeaderText="State" DataField="state" SortExpression="state" />
<asp:BoundField HeaderText="Zip Code" DataField="zip" SortExpression="zip" />
<asp:CheckBoxField HeaderText="Contract" SortExpression="contract" DataField="contract" />
<asp:HyperLinkField HeaderText="View Details..." Text="View Details..." DataNavigateUrlFields="au_id"
DataNavigateUrlFormatString="DetailsView_cs.aspx?ID={0}" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" Runat="server" SelectCommand="SELECT [au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract] FROM [authors] WHERE [state] = @state"
ConnectionString="<%$ ConnectionStrings:Pubs %>">
<SelectParameters>
<asp:ControlParameter Name="state" ControlID="DropDownList1" />
</SelectParameters>
</asp:SqlDataSource>
</form>
</body>
</html>
DetailsView_cs.aspx
<%@ Page Language="C#" %>
<html>
<head runat="server">
<title>DetailsView</title>
</head>
<body>
<form id="form1" runat="server">
<asp:DetailsView ID="DetailsView1" Runat="server" DataSourceID="SqlDataSource1" AutoGenerateRows="False"
HeaderText="Books for Author" AllowPaging="True">
<Fields>
<asp:BoundField HeaderText="au_id" DataField="au_id" SortExpression="au_id" />
<asp:BoundField HeaderText="title_id" DataField="title_id" SortExpression="title_id" />
<asp:BoundField HeaderText="title" DataField="title" SortExpression="title" />
<asp:BoundField HeaderText="type" DataField="type" SortExpression="type" />
<asp:BoundField HeaderText="price" DataField="price" SortExpression="price" />
<asp:BoundField HeaderText="notes" DataField="notes" SortExpression="notes" />
</Fields>
</asp:DetailsView>
<asp:SqlDataSource ID="SqlDataSource1" Runat="server" SelectCommand="SELECT dbo.authors.au_id, dbo.titles.title_id, dbo.titles.title, dbo.titles.type, dbo.titles.price, dbo.titles.notes FROM dbo.authors INNER JOIN dbo.titleauthor ON dbo.authors.au_id = dbo.titleauthor.au_id INNER JOIN dbo.titles ON dbo.titleauthor.title_id = dbo.titles.title_id WHERE (dbo.authors.au_id = @au_id)"
ConnectionString="<%$ ConnectionStrings:Pubs %>">
<SelectParameters>
<asp:QueryStringParameter Name="au_id" DefaultValue="213-46-8915" QueryStringField="ID" />
</SelectParameters>
</asp:SqlDataSource>
</form>
</body>
</html>
插入数据
与 GridView 控件相似,DetailsView 控件支持通过数据源更新和删除数据。但是,DetailsView 还支持插入数据,而 GridView 不支持。可以轻松地将 DetailsView 和 GridView 配对,以使插入的记录显示在 GridView 控件中。
若要使 SqlDataSource 支持 Insert,请将 InsertCommand 属性设置为有效的插入命令,其中带有 DetailsView 控件在 Insert 模式下呈现的每个字段值的参数占位符。还可以选择指定一个 InsertParameters 集合来包含用于此操作的数据参数对象。
若要启用用于插入的 UI,请将 AutoGenerateInsertButton 属性设置为 true 或向 DetailsView Fields 集合添加 ShowInsertButton 设置为 true 的 CommandField。若要将 DetailsView 置于插入模式,请单击“New”(新建)按钮。当处于插入模式时,DetailsView 将呈现每个字段的输入控件。注意,标记为 ReadOnly 的字段在 Insert 模式下被呈现为输入控件(虽然它们在 Update 模式下不会被呈现为输入控件)。若要从 Insert 模式排除某一字段,请将该字段的 InsertVisible 属性设置为 false。若要提交插入操作,请在插入模式下单击“Insert”(插入)按钮。若要中止插入操作,请单击“Cancel”(取消)按钮。
当 Insert 操作被提交时,DetailsView 从其输入控件收集值,并填充一个 Values 字典以传递给数据源。SqlDataSource 在执行命令之前将这些值应用于 InsertCommand 的参数集合。与 Update 一样,自动插入功能依赖于 InsertCommand 中名称与从选择操作返回的字段完全相同的参数。注意,Insert 不需要 Keys 字典。
<%@ Page Language="C#" %>
<script runat="server">
protected void DetailsView1_ItemInserted(Object sender, System.Web.UI.WebControls.DetailsViewInsertedEventArgs e)
{
if (e.Exception != null)
{
ErrorMessageLabel.Text = "An error occured while entering this record. Please verify you have entered data in the correct format.";
e.ExceptionHandled = true;
}
GridView1.DataBind();
}
protected void DetailsView1_ItemUpdated(Object sender, System.Web.UI.WebControls.DetailsViewUpdatedEventArgs e)
{
GridView1.DataBind();
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
DetailsView1.ChangeMode(DetailsViewMode.ReadOnly);
}
protected void GridView1_SelectedIndexChanged(object sender, EventArgs e)
{
DetailsView1.ChangeMode(DetailsViewMode.ReadOnly);
}
protected void GridView1_PageIndexChanged(object sender, EventArgs e)
{
DetailsView1.ChangeMode(DetailsViewMode.ReadOnly);
}
protected void GridView1_Sorted(object sender, EventArgs e)
{
DetailsView1.ChangeMode(DetailsViewMode.ReadOnly);
}
protected void GridView1_RowDeleted(object sender, GridViewDeletedEventArgs e)
{
if (e.Exception != null)
{
ErrorMessageLabel.Text = "Failed to DELETE due to foreign key contstraint on the table. You may only delete rows which have no related records.";
e.ExceptionHandled = true;
}
}
protected void DetailsView1_DataBound(object sender, EventArgs e)
{
if (DetailsView1.CurrentMode == DetailsViewMode.Insert)
{
TextBox stateTextBox = (TextBox)DetailsView1.Rows[6].Cells[1].Controls[0];
stateTextBox.Text = DropDownList1.SelectedValue;
stateTextBox.Enabled = false;
}
}
</script>
<html>
<head runat="server">
<title>GridView DetailsView Master-Details (Insert)</title>
</head>
<body>
<form id="form1" runat="server">
<b>Choose a state:</b>
<asp:DropDownList ID="DropDownList1" DataSourceID="SqlDataSource2" AutoPostBack="true"
DataTextField="state" runat="server" OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged" />
<asp:SqlDataSource ID="SqlDataSource2" runat="server" SelectCommand="SELECT DISTINCT [state] FROM [authors]"
ConnectionString="<%$ ConnectionStrings:Pubs %>" />
<br />
<br />
<table>
<tr>
<td valign="top">
<asp:GridView ID="GridView1" AllowSorting="True" AllowPaging="True" runat="server"
DataSourceID="SqlDataSource1" DataKeyNames="au_id"
AutoGenerateColumns="False" Width="500px" SelectedIndex="0" OnSelectedIndexChanged="GridView1_SelectedIndexChanged" OnPageIndexChanged="GridView1_PageIndexChanged" OnRowDeleted="GridView1_RowDeleted" OnSorted="GridView1_Sorted">
<Columns>
<asp:CommandField ShowSelectButton="true" ShowDeleteButton="true" />
<asp:BoundField DataField="au_id" HeaderText="au_id" ReadOnly="True" SortExpression="au_id" />
<asp:BoundField DataField="au_lname" HeaderText="au_lname" SortExpression="au_lname" />
<asp:BoundField DataField="au_fname" HeaderText="au_fname" SortExpression="au_fname" />
<asp:BoundField DataField="state" HeaderText="state" SortExpression="state" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:Pubs %>"
SelectCommand="SELECT [au_id], [au_lname], [au_fname], [state] FROM [authors] WHERE ([state] = @state)"
DeleteCommand="DELETE FROM [authors] WHERE [au_id] = @au_id">
<SelectParameters>
<asp:ControlParameter ControlID="DropDownList1" Name="state" PropertyName="SelectedValue"
Type="String" />
</SelectParameters>
</asp:SqlDataSource>
</td>
<td valign="top">
<asp:DetailsView AutoGenerateRows="False" DataKeyNames="au_id" DataSourceID="SqlDataSource3"
HeaderText="Author Details" ID="DetailsView1" runat="server" Width="275px" OnItemUpdated="DetailsView1_ItemUpdated" OnItemInserted="DetailsView1_ItemInserted" OnDataBound="DetailsView1_DataBound">
<Fields>
<asp:BoundField DataField="au_id" HeaderText="au_id" ReadOnly="True" SortExpression="au_id" />
<asp:BoundField DataField="au_lname" HeaderText="au_lname" SortExpression="au_lname" />
<asp:BoundField DataField="au_fname" HeaderText="au_fname" SortExpression="au_fname" />
<asp:BoundField DataField="phone" HeaderText="phone" SortExpression="phone" />
<asp:BoundField DataField="address" HeaderText="address" SortExpression="address" />
<asp:BoundField DataField="city" HeaderText="city" SortExpression="city" />
<asp:BoundField DataField="state" HeaderText="state" SortExpression="state" />
<asp:BoundField DataField="zip" HeaderText="zip" SortExpression="zip" />
<asp:CheckBoxField DataField="contract" HeaderText="contract" SortExpression="contract" />
<asp:CommandField ShowEditButton="True" ShowInsertButton="True" />
</Fields>
</asp:DetailsView>
<asp:SqlDataSource ID="SqlDataSource3" runat="server" ConnectionString="<%$ ConnectionStrings:Pubs %>"
SelectCommand="SELECT [au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract] FROM [authors] WHERE ([au_id] = @au_id)"
UpdateCommand="UPDATE [authors] SET [au_lname] = @au_lname, [au_fname] = @au_fname, [phone] = @phone, [address] = @address, [city] = @city, [state] = @state, [zip] = @zip, [contract] = @contract WHERE [au_id] = @au_id"
InsertCommand="INSERT INTO [authors] ([au_id], [au_lname], [au_fname], [phone], [address], [city], [state], [zip], [contract]) VALUES (@au_id, @au_lname, @au_fname, @phone, @address, @city, @state, @zip, @contract)">
<SelectParameters>
<asp:ControlParameter ControlID="GridView1" Name="au_id" PropertyName="SelectedValue"
Type="String" />
</SelectParameters>
<UpdateParameters>
<asp:Parameter Name="au_lname" Type="String" />
<asp:Parameter Name="au_fname" Type="String" />
<asp:Parameter Name="phone" Type="String" />
<asp:Parameter Name="address" Type="String" />
<asp:Parameter Name="city" Type="String" />
<asp:Parameter Name="state" Type="String" />
<asp:Parameter Name="zip" Type="String" />
<asp:Parameter Name="contract" Type="Boolean" />
<asp:Parameter Name="au_id" Type="String" />
</UpdateParameters>
<InsertParameters>
<asp:Parameter Name="au_id" Type="String" />
<asp:Parameter Name="au_lname" Type="String" />
<asp:Parameter Name="au_fname" Type="String" />
<asp:Parameter Name="phone" Type="String" />
<asp:Parameter Name="address" Type="String" />
<asp:Parameter Name="city" Type="String" />
<asp:Parameter Name="state" Type="String" />
<asp:Parameter Name="zip" Type="String" />
<asp:Parameter Name="contract" Type="Boolean" />
</InsertParameters>
</asp:SqlDataSource>
</td>
</tr>
</table>
<br />
<asp:Label ID="ErrorMessageLabel" EnableViewState="false" runat="server" />
</form>
</body>
</html>
与 GridView 控件相似,DetailsView 控件支持通过数据源更新和删除数据。但是,DetailsView 还支持插入数据,而 GridView 不支持。可以轻松地将 DetailsView 和 GridView 配对,以使插入的记录显示在 GridView 控件中。
若要使 SqlDataSource 支持 Insert,请将 InsertCommand 属性设置为有效的插入命令,其中带有 DetailsView 控件在 Insert 模式下呈现的每个字段值的参数占位符。还可以选择指定一个 InsertParameters 集合来包含用于此操作的数据参数对象。
若要启