使用 DataList 和 Repeater 控件显示数据 (VB)
作者 :斯科特·米切尔
在前面的教程中,我们使用了 GridView 控件来显示数据。 从本教程开始,我们将了解如何使用 DataList 和 Repeater 控件构建常见的报告模式,从使用这些控件显示数据的基础知识开始。
介绍
在过去 28 个教程中的所有示例中,如果需要显示数据源中的多个记录,我们转向 GridView 控件。 GridView 为数据源中的每个记录呈现一行,并在列中显示记录的数据字段。 虽然 GridView 使它成为显示、分页、排序、编辑和删除数据的对齐方式,但其外观有点框。 此外,负责 GridView 结构的标记是固定的,它包含一个 HTML <table>
,其中包含每个记录的表行(<tr>
)和每个字段的表单元格(<td>
)。
为了在显示多个记录时在外观和呈现标记中提供更大的自定义度,ASP.NET 2.0 提供 DataList 和 Repeater 控件(这两个控件在 1.x 版 ASP.NET 中也可用)。 DataList 和 Repeater 控件使用模板而不是 BoundFields、CheckBoxFields、ButtonFields 等呈现其内容。 与 GridView 一样,DataList 呈现为 HTML <table>
,但允许每个表行显示多个数据源记录。 另一方面,Repeater 不会呈现任何显式指定的标记,并且当需要精确控制所发出的标记时,该标记是理想的候选项。
在接下来的十几篇左右教程中,我们将介绍如何使用 DataList 和 Repeater 控件构建常见的报告模式,从使用这些控件模板显示数据的基础知识开始。 我们将了解如何设置这些控件的格式、如何更改 DataList 中数据源记录的布局、常见的主/详细信息方案、编辑和删除数据的方法、如何翻页浏览记录等。
步骤 1:添加 DataList 和 Repeater 教程网页
在开始本教程之前,让我们先花点时间添加本教程所需的 ASP.NET 页面,接下来的几个教程介绍如何使用 DataList 和 Repeater 显示数据。 首先在名为 <Site.master
:
Default.aspx
Basics.aspx
Formatting.aspx
RepeatColumnAndDirection.aspx
NestedControls.aspx
图 1:创建 DataListRepeaterBasics
文件夹并添加教程 ASP.NET 页面
Default.aspx
打开页面并将用户控件从UserControls
文件夹拖动SectionLevelTutorialListing.ascx
到设计图面上。 我们在母版页和网站导航教程中创建的此用户控件枚举网站地图,并在项目符号列表中显示当前部分中的教程。
图 2:将用户控件Default.aspx
添加到 SectionLevelTutorialListing.ascx
(单击以查看全尺寸图像)
为了使项目符号列表显示要创建的 DataList 和 Repeater 教程,我们需要将它们添加到站点地图。 Web.sitemap
打开该文件,并在添加自定义按钮站点映射节点标记后添加以下标记:
<siteMapNode
title="Displaying Data with the DataList and Repeater"
description="Samples of Reports that Use the DataList and Repeater Controls"
url="~/DataListRepeaterBasics/Default.aspx" >
<siteMapNode
title="Basic Examples"
description="Examines the basics for displaying data using the
DataList and Repeater controls."
url="~/DataListRepeaterBasics/Basics.aspx" />
<siteMapNode
title="Formatting"
description="Learn how to format the DataList and the Web controls within
the DataList and Repeater's templates."
url="~/DataListRepeaterBasics/Formatting.aspx" />
<siteMapNode
title="Adjusting the DataList s Layout"
description="Illustrates how to alter the DataList's layout, showing
multiple data source records per table row."
url="~/DataListRepeaterBasics/RepeatColumnAndDirection.aspx" />
<siteMapNode
title="Nesting a Repeater within a DataList"
description="Learn how to nest a Repeater within the template of a DataList."
url="~/DataListRepeaterBasics/NestedControls.aspx" />
</siteMapNode>
图 3:更新网站地图以包括新的 ASP.NET 页
步骤 2:使用 DataList 显示产品信息
与 FormView 类似,DataList 控件的呈现输出取决于模板,而不是 BoundFields、CheckBoxFields 等。 与 FormView 不同,DataList 旨在显示一组记录,而不是单独记录。 让我们开始本教程,了解如何将产品信息绑定到 DataList。 首先打开 Basics.aspx
文件夹中的页面 DataListRepeaterBasics
。 接下来,将 DataList 从工具箱拖到设计器上。 如图 4 所示,在指定 DataList 模板之前,设计器将其显示为灰色框。
图 4:将 DataList 从工具箱拖到设计器上(单击以查看全尺寸图像)
从 DataList 的智能标记中,添加新的 ObjectDataSource 并将其配置为使用 ProductsBLL
类的方法 GetProducts
。 由于我们在本教程中重新创建只读 DataList,因此请在向导的 INSERT、UPDATE 和 DELETE 选项卡中将下拉列表设置为“无”。
图 5:选择创建新的 ObjectDataSource(单击以查看全尺寸图像)
图 6:将 ObjectDataSource 配置为使用 ProductsBLL
类(单击以查看全尺寸图像)
图 7:使用 GetProducts
该方法检索有关所有产品的信息(单击以查看全尺寸图像)
配置 ObjectDataSource 并通过其智能标记将其与 DataList 关联后,Visual Studio 将自动在 DataList 中创建一个 ItemTemplate
,其中显示数据源返回的每个数据字段的名称和值(请参阅下面的标记)。 此默认 ItemTemplate
外观与通过设计器将数据源绑定到 FormView 时自动创建的模板的外观相同。
<asp:DataList ID="DataList1" runat="server" DataKeyField="ProductID"
DataSourceID="ObjectDataSource1" EnableViewState="False">
<ItemTemplate>
ProductID: <asp:Label ID="ProductIDLabel" runat="server"
Text='<%# Eval("ProductID") %>' /><br />
ProductName: <asp:Label ID="ProductNameLabel" runat="server"
Text='<%# Eval("ProductName") %>' /><br />
SupplierID: <asp:Label ID="SupplierIDLabel" runat="server"
Text='<%# Eval("SupplierID") %>' /><br />
CategoryID: <asp:Label ID="CategoryIDLabel" runat="server"
Text='<%# Eval("CategoryID") %>'/><br />
QuantityPerUnit: <asp:Label ID="QuantityPerUnitLabel" runat="server"
Text='<%# Eval("QuantityPerUnit") %>' /><br />
UnitPrice: <asp:Label ID="UnitPriceLabel" runat="server"
Text='<%# Eval("UnitPrice") %>' /><br />
UnitsInStock: <asp:Label ID="UnitsInStockLabel" runat="server"
Text='<%# Eval("UnitsInStock") %>' /><br />
UnitsOnOrder: <asp:Label ID="UnitsOnOrderLabel" runat="server"
Text='<%# Eval("UnitsOnOrder") %>' /><br />
ReorderLevel: <asp:Label ID="ReorderLevelLabel" runat="server"
Text='<%# Eval("ReorderLevel") %>' /><br />
Discontinued: <asp:Label ID="DiscontinuedLabel" runat="server"
Text='<%# Eval("Discontinued") %>' /><br />
CategoryName: <asp:Label ID="CategoryNameLabel" runat="server"
Text='<%# Eval("CategoryName") %>' /><br />
SupplierName: <asp:Label ID="SupplierNameLabel" runat="server"
Text='<%# Eval("SupplierName") %>' /><br />
<br />
</ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProducts" TypeName="ProductsBLL">
</asp:ObjectDataSource>
注意
回想一下,当通过 FormView 智能标记将数据源绑定到 FormView 控件时,Visual Studio 创建了一个ItemTemplate
和InsertItemTemplate
EditItemTemplate
。 但是,使用 DataList 时,只会创建一个 ItemTemplate
。 这是因为 DataList 没有 FormView 提供的相同内置编辑和插入支持。 DataList 包含与编辑和删除相关的事件,并且可以使用一些代码添加编辑和删除支持,但与 FormView 一样,没有简单的现成支持。 我们将在未来的教程中了解如何包括对 DataList 的编辑和删除支持。
让我们花点时间改进此模板的外观。 我们仅显示产品名称、供应商、类别、每个单位的数量和单价,而不是显示所有数据字段。 此外,让我们在标题中 <h4>
显示名称,并使用 <table>
标题下方的其余字段进行布局。
若要进行这些更改,可以使用 DataList 智能标记中的设计器中的模板编辑功能单击“编辑模板”链接,也可以通过页面声明性语法手动修改模板。 如果在设计器中使用“编辑模板”选项,生成的标记可能与以下标记完全不匹配,但在通过浏览器查看时,其外观应与图 8 中显示的屏幕截图非常相似。
<asp:DataList ID="DataList1" runat="server" DataKeyField="ProductID"
DataSourceID="ObjectDataSource1" EnableViewState="False">
<ItemTemplate>
<h4><asp:Label ID="ProductNameLabel" runat="server"
Text='<%# Eval("ProductName") %>' /></h4>
<table border="0">
<tr>
<td class="ProductPropertyLabel">Category:</td>
<td><asp:Label ID="CategoryNameLabel" runat="server"
Text='<%# Eval("CategoryName") %>' /></td>
<td class="ProductPropertyLabel">Supplier:</td>
<td><asp:Label ID="SupplierNameLabel" runat="server"
Text='<%# Eval("SupplierName") %>' /></td>
</tr>
<tr>
<td class="ProductPropertyLabel">Qty/Unit:</td>
<td><asp:Label ID="QuantityPerUnitLabel" runat="server"
Text='<%# Eval("QuantityPerUnit") %>' /></td>
<td class="ProductPropertyLabel">Price:</td>
<td><asp:Label ID="UnitPriceLabel" runat="server"
Text='<%# Eval("UnitPrice", "{0:C}") %>' /></td>
</tr>
</table>
</ItemTemplate>
</asp:DataList>
注意
上面的示例使用标签 Web 控件,其 Text
属性分配了数据绑定语法的值。 或者,我们可以完全省略标签,只需键入数据绑定语法。 也就是说,可以改用声明性语法,而不是 <asp:Label ID="CategoryNameLabel" runat="server" Text='<%# Eval("CategoryName") %>' />
使用声明性语法 <%# Eval("CategoryName") %>
。
但是,留在标签 Web 控件中提供了两个优点。 首先,它提供了一种更简单的方法,用于基于数据设置数据的格式,如下一教程中所示。 其次,设计器中的“编辑模板”选项不显示某些 Web 控件外部显示的声明性数据绑定语法。 相反,“编辑模板”界面旨在促进使用静态标记和 Web 控件,并假定任何数据绑定将通过“编辑 DataBindings”对话框完成,该对话框可从 Web 控件智能标记访问。
因此,使用 DataList 时,它提供通过设计器编辑模板的选项,我更喜欢使用标签 Web 控件,以便可以通过“编辑模板”界面访问内容。 正如我们不久将看到的那样,Repeater 要求从源视图编辑模板的内容。 因此,在创建 Repeater 模板时,我通常会省略标签 Web 控件,除非我知道我需要基于编程逻辑设置数据绑定文本的外观。
图 8:使用 DataList s ItemTemplate
呈现每个产品的输出(单击以查看全尺寸图像)
步骤 3:改进 DataList 的外观
与 GridView 一样,DataList 提供了许多与样式相关的属性,例如Font
、、、BackColor
、ItemStyle
CssClass
、AlternatingItemStyle
、 等SelectedItemStyle
ForeColor
。 使用 GridView 和 DetailsView 控件时,我们在主题中创建DataWebControls
“外观”文件,该文件预定义CssClass
了这两个控件的属性,以及CssClass
其中几个子属性的属性(RowStyle
HeaderStyle
等等)。 让我们对 DataList 执行相同的操作。
如“使用 ObjectDataSource 显示数据”教程中所述,外观文件指定 Web 控件的默认外观相关属性;主题是用于定义网站特定外观的皮肤、CSS、图像和 JavaScript 文件的集合。 在“使用 ObjectDataSource 显示数据”教程中,我们创建了一个主题(该主题作为文件夹内App_Themes
的文件夹实现),该主题当前包含两个 DataWebControls
Skin 文件 - GridView.skin
和 DetailsView.skin
。 让我们添加第三个外观文件,以指定 DataList 的预定义样式设置。
若要添加外观文件,请 App_Themes/DataWebControls
右键单击文件夹,选择“添加新项”,然后从列表中选择“皮肤文件”选项。 为 DataList.skin
文件命名。
图 9:新建名为 DataList.skin
“外观文件”(单击以查看全尺寸图像)
对文件使用以下标记 DataList.skin
:
<asp:DataList runat="server" CssClass="DataWebControlStyle">
<AlternatingItemStyle CssClass="AlternatingRowStyle" />
<ItemStyle CssClass="RowStyle" />
<HeaderStyle CssClass="HeaderStyle" />
<FooterStyle CssClass="FooterStyle" />
<SelectedItemStyle CssClass="SelectedRowStyle" />
</asp:DataList>
这些设置将相同的 CSS 类分配给与 GridView 和 DetailsView 控件一起使用的相应 DataList 属性。 此处DataWebControlStyle
使用的 CSS 类、AlternatingRowStyle
RowStyle
等等在Styles.css
文件中定义,并在前面的教程中添加。
添加此外观文件后,DataList 的外观将在设计器中更新(可能需要刷新设计器视图才能查看新外观文件的效果;从“视图”菜单中选择“刷新”)。 如图 10 所示,每个交替产品的背景色为浅粉色。
图 10:创建新的外观文件(DataList.skin
单击以查看全尺寸图像)
步骤 4:浏览 DataList 的其他模板
除此 ItemTemplate
以外,DataList 还支持其他六个可选模板:
HeaderTemplate
如果提供,则向输出添加标题行,并用于呈现此行AlternatingItemTemplate
用于呈现交替项SelectedItemTemplate
用于呈现所选项;所选项是其索引对应于 DataList s 属性的SelectedIndex
项EditItemTemplate
用于呈现正在编辑的项目SeparatorTemplate
如果提供,则在每个项之间添加分隔符,并用于呈现此分隔符FooterTemplate
- 如果提供,则向输出添加页脚行,并用于呈现此行
指定 HeaderTemplate
或 FooterTemplate
时,DataList 会将其他页眉或页脚行添加到呈现的输出中。 与 GridView 的页眉和页脚行一样,DataList 中的页眉和页脚不会绑定到数据。 因此,尝试访问绑定数据的任何FooterTemplate
数据绑定语法HeaderTemplate
都将返回一个空白字符串。
注意
正如我们在 GridView 页脚中显示摘要信息教程中看到 的那样,虽然页眉和页脚 行不支持数据绑定语法,但数据特定的信息可以直接注入到 GridView 事件处理程序的 RowDataBound
这些行中。 此方法可用于计算绑定到控件的数据的运行总计或其他信息,以及将该信息分配给页脚。 相同的概念可以应用于 DataList 和 Repeater 控件;唯一的区别是,对于 DataList 和 Repeater,为 ItemDataBound
事件(而不是事件 RowDataBound
)创建事件处理程序。
对于我们的示例,让我们将标题“产品信息”显示在 DataList 结果顶部的标题中 <h3>
。 为此,请使用相应的标记添加一个 HeaderTemplate
。 从设计器中,可以通过单击 DataList 智能标记中的“编辑模板”链接、从下拉列表中选择标题模板,然后在从样式下拉列表中选择“标题 3”选项后键入文本(请参阅图 11)。
图 11:使用文本产品信息添加 a HeaderTemplate
(单击可查看全尺寸图像)
或者,可以通过在标记中 <asp:DataList>
输入以下标记来以声明方式添加此项:
<HeaderTemplate>
<h3>Product Information</h3>
</HeaderTemplate>
若要在每个产品列表之间添加一点空间,让我们添加一个 SeparatorTemplate
包含每个部分之间的行的行。 水平规则标记(<hr>
)添加这样的分隔符。 SeparatorTemplate
创建使其具有以下标记:
<SeparatorTemplate>
<hr />
</SeparatorTemplate>
注意
HeaderTemplate
与该FooterTemplates
数据源一样,SeparatorTemplate
该记录不会绑定到数据源中的任何记录,因此无法直接访问绑定到 DataList 的数据源记录。
添加后,通过浏览器查看页面时,它应类似于图 12。 请注意每个产品列表之间的标题行和行。
图 12:DataList 包括标题行和每个产品列表之间的水平规则(单击以查看全尺寸图像)
步骤 5:使用 Repeater 控件呈现特定标记
如果在从图 12 访问 DataList 示例时从浏览器执行视图/源,则会看到 DataList 会发出一个 HTML <table>
,其中包含一个表行(<tr>
)以及绑定到 DataList 的每个项的单个表单元格(<td>
)。 事实上,此输出与使用单个 TemplateField 的 GridView 发出的输出相同。 正如我们在将来的教程中看到的那样,DataList 确实允许进一步自定义输出,使我们能够显示每个表行的多个数据源记录。
不过,如果不想发出 HTML <table>
,该怎么办? 若要对数据 Web 控件生成的标记进行总计和完全控制,必须使用 Repeater 控件。 与 DataList 一样,Repeater 是基于模板构造的。 但是,Repeater 仅提供以下五个模板:
HeaderTemplate
如果提供,在项之前添加指定的标记ItemTemplate
用于呈现项AlternatingItemTemplate
如果提供,则用于呈现交替项SeparatorTemplate
如果提供,则在每个项之间添加指定的标记FooterTemplate
- 如果提供,则添加项后的指定标记
在 ASP.NET 1.x 中,Repeater 控件通常用于显示其数据来自某些数据源的项目符号列表。 在这种情况下, HeaderTemplate
将 FooterTemplates
分别包含开始标记和结束 <ul>
标记,而 ItemTemplate
将包含 <li>
具有数据绑定语法的元素。 此方法仍可在 ASP.NET 2.0 中使用,如母版页和网站导航教程中的两个示例所示:
- 在母版页中
Site.master
,Repeater 用于显示顶级网站地图内容的项目符号列表(基本报告、筛选报表、自定义格式等);另一个嵌套的 Repeater 用于显示顶级节的子节 - 在 中
SectionLevelTutorialListing.ascx
,Repeater 用于显示当前站点地图部分子节的项目符号列表
注意
ASP.NET 2.0 引入了新的 BulletedList 控件,该控件可以绑定到数据源控件以显示简单的项目符号列表。 使用 BulletedList 控件,我们不需要指定任何与列表相关的 HTML;相反,我们只是指示要显示为每个列表项的文本的数据字段。
Repeater 充当捕获所有数据 Web 控件。 如果没有生成所需标记的现有控件,则可以使用 Repeater 控件。 为了说明如何使用 Repeater,让我们将类别列表显示在步骤 2 中创建的产品信息 DataList 上方。 具体而言,让我们将类别显示在单行 HTML <table>
中,每个类别都显示为表中的列。
为此,首先将 Repeater 控件从工具箱拖到设计器上,再将产品信息 DataList 上方拖到设计器上。 与 DataList 一样,Repeater 最初显示为灰色框,直到定义其模板。
图 13:向设计器添加重复程序(单击以查看全尺寸图像)
Repeater 智能标记中只有一个选项:选择数据源。 选择创建新的 ObjectDataSource 并将其配置为使用 CategoriesBLL
类的方法 GetCategories
。
图 14:创建新的 ObjectDataSource(单击可查看全尺寸图像)
图 15:将 ObjectDataSource 配置为使用 CategoriesBLL
类(单击以查看全尺寸图像)
图 16:使用 GetCategories
该方法检索有关所有类别的信息(单击以查看全尺寸图像)
与 DataList 不同,Visual Studio 不会在将 Repeater 绑定到数据源后自动创建 ItemTemplate。 此外,Repeater 的模板不能通过设计器进行配置,并且必须以声明方式指定。
若要将类别显示为包含每个类别的列的单行 <table>
,我们需要 Repeater 发出类似于以下内容的标记:
<table>
<tr>
<td>Category 1</td>
<td>Category 2</td>
...
<td>Category N</td>
</tr>
</table>
<td>Category X</td>
由于文本是重复的部分,因此这将显示在 Repeater s ItemTemplate 中。 出现在它的标记 - <table><tr>
将放置在 HeaderTemplate
结束标记 - </tr></table>
将放置在其中 FooterTemplate
。 若要输入这些模板设置,请单击左下角的“源”按钮并键入以下语法,转到 ASP.NET 页的声明性部分:
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource2"
EnableViewState="False">
<HeaderTemplate>
<table>
<tr>
</HeaderTemplate>
<ItemTemplate>
<td><%# Eval("CategoryName") %></td>
</ItemTemplate>
<FooterTemplate>
</tr>
</table>
</FooterTemplate>
</asp:Repeater>
Repeater 将发出由其模板指定的精确标记,只不过是少一些。 图 17 显示了通过浏览器查看时 Repeater 的输出。
图 17:单行 HTML <table>
列出单独列中每个类别(单击以查看全尺寸图像)
步骤 6:改进重复程序的外观
由于 Repeater 准确地发出由其模板指定的标记,因此,对于 Repeater 没有与样式相关的属性并不奇怪。 若要更改 Repeater 生成的内容的外观,必须手动将所需的 HTML 或 CSS 内容直接添加到 Repeater 模板中。
在本示例中,让我们让类别列交替背景色,如 DataList 中的交替行。 为此,我们需要将 CSS 类分配给 RowStyle
每个 Repeater 项,并将 AlternatingRowStyle
CSS 类分配给每个 ItemTemplate
交替的 Repeater 项以及 AlternatingItemTemplate
模板,如下所示:
<ItemTemplate>
<td class="RowStyle"><%# Eval("CategoryName") %></td>
</ItemTemplate>
<AlternatingItemTemplate>
<td class="AlternatingRowStyle"><%# Eval("CategoryName") %></td>
</AlternatingItemTemplate>
我们还使用文本“产品类别”向输出添加标题行。 由于我们不知道将包含<table>
多少列,因此生成保证跨所有列的标题行的最简单方法是使用两<table>
个列。 第一 <table>
行将包含标题行的两行,一行将包含第二行,该行 <table>
包含系统中每个类别的列。 也就是说,我们要发出以下标记:
<table>
<tr>
<th>Product Categories</th>
</tr>
<tr>
<td>
<table>
<tr>
<td>Category 1</td>
<td>Category 2</td>
...
<td>Category N</td>
</tr>
</table>
</td>
</tr>
</table>
以下 HeaderTemplate
代码并 FooterTemplate
生成所需的标记:
<asp:Repeater ID="Repeater1" runat="server" DataSourceID="ObjectDataSource2"
EnableViewState="False">
<HeaderTemplate>
<table cellpadding="0" cellspacing="0">
<tr>
<th class="HeaderStyle">Product Categories</th>
</tr>
<tr>
<td>
<table cellpadding="4" cellspacing="0">
<tr>
</HeaderTemplate>
<ItemTemplate>
<td class="RowStyle"><%# Eval("CategoryName") %></td>
</ItemTemplate>
<AlternatingItemTemplate>
<td class="AlternatingRowStyle">
<%# Eval("CategoryName") %></td>
</AlternatingItemTemplate>
<FooterTemplate>
</tr>
</table>
</td>
</tr>
</table>
</FooterTemplate>
</asp:Repeater>
图 18 显示了这些更改后重复程序。
图 18:背景色中的类别列交替并包括标题行(单击以查看全尺寸图像)
总结
虽然 GridView 控件可以轻松显示、编辑、删除、排序和页面浏览数据,但外观非常框和网格一样。 为了更好地控制外观,我们需要转向 DataList 或 Repeater 控件。 这两个控件都使用模板而不是 BoundFields、CheckBoxFields 等显示一组记录。
DataList 呈现为 HTML <table>
,默认情况下,在单个表行中显示每个数据源记录,就像使用单个 TemplateField 的 GridView 一样。 但是,在将来的教程中,DataList 确实允许每个表行显示多个记录。 另一方面,Repeater 严格发出其模板中指定的标记;它不添加任何其他标记,因此通常用于在除项目符号列表中以外的 <table>
HTML 元素中显示数据。
虽然 DataList 和 Repeater 在呈现的输出中提供了更大的灵活性,但它们缺少 GridView 中找到的许多内置功能。 正如我们在即将推出的教程中介绍的,其中一些功能可以插入,无需太多精力,但请记住,使用 DataList 或 Repeater 代替 GridView 确实会限制可以使用的功能,而无需自行实现这些功能。
快乐编程!
关于作者
斯科特·米切尔,七本 ASP/ASP.NET 书籍的作者和 4GuysFromRolla.com 的创始人,自1998年以来一直在与Microsoft Web 技术合作。 斯科特担任独立顾问、教练和作家。 他的最新书是 山姆斯在24小时内 ASP.NET 2.0。 他可以通过他的博客联系到mitchell@4GuysFromRolla.com他,可以在该博客中找到http://ScottOnWriting.NET。
特别感谢
本教程系列由许多有用的审阅者审阅。 本教程的主要审阅者是 Yaakov Ellis、Liz Shulok、Randy Schmidt 和 Stacy Park。 有兴趣查看即将发布的 MSDN 文章? 如果是这样,请把我扔一条线。mitchell@4GuysFromRolla.com