作者 :斯科特·米切尔
可以通过多种方式根据绑定到 GridView、DetailsView 或 FormView 的数据调整其格式。 在本教程中,我们将了解如何通过使用 DataBound 和 RowDataBound 事件处理程序来完成数据绑定格式设置。
介绍
GridView、DetailsView 和 FormView 控件的外观可以通过大量与样式相关的属性进行自定义。 、 CssClass
、 Font
BorderWidth
、 BorderStyle
BorderColor
Width
和 Height
等属性决定了呈现的控件的一般外观。 包括 HeaderStyle
、 、 RowStyle
AlternatingRowStyle
、 和其他属性 允许将这些相同的样式设置应用于特定部分。 同样,这些样式设置可以在字段级别应用。
但是,在许多情况下,格式设置要求取决于所显示数据的值。 例如,为了引起对缺货产品的注意,列出产品信息的报表可能会将 and UnitsInStock
字段均等于 0 的产品UnitsOnOrder
的背景颜色设置为黄色。 为了突出显示价格较高的商品,我们可能希望以粗体显示价格超过 $75.00 的商品的价格。
可以通过多种方式根据绑定到 GridView、DetailsView 或 FormView 的数据调整其格式。 在本教程中,我们将了解如何通过使用 DataBound
和 RowDataBound
事件处理程序来完成数据绑定格式设置。 在下一个教程中,我们将探索另一种方法。
使用 DetailsView 控件的事件DataBound
处理程序
当数据绑定到 DetailsView 时,无论是从数据源控件还是通过以编程方式将数据分配给控件的属性 DataSource
并调用其 DataBind()
方法,将执行以下步骤序列:
- 数据 Web 控件的事件
DataBinding
触发。 - 数据将绑定到数据 Web 控件。
- 数据 Web 控件的事件
DataBound
触发。
自定义逻辑可以在步骤 1 和 3 之后通过事件处理程序立即注入。 通过为 DataBound
事件创建事件处理程序,我们可以通过编程方式确定已绑定到数据 Web 控件的数据,并根据需要调整格式。 为了说明这一点,让我们创建一个 DetailsView,它将列出有关产品的一般信息,但如果该值超过 75.00 美元,它将以UnitPrice
该值。
步骤 1:在 DetailsView 中展示产品信息
打开文件夹中的 CustomColors.aspx
页面 CustomFormatting
,将 DetailsView 控件从 Toolbox 拖到 Designer 上,将其 ID
属性值设置为 ExpensiveProductsPriceInBoldItalic
,然后将其绑定到调用 ProductsBLL
该类 GetProducts()
方法的新 ObjectDataSource 控件。 为简洁起见,此处省略了完成此作的详细步骤,因为我们在前面的教程中详细研究了这些步骤。
将 ObjectDataSource 绑定到 DetailsView 后,请花点时间修改字段列表。 我选择删除 ProductID
、 、 SupplierID
CategoryID
、 UnitsInStock
UnitsOnOrder
ReorderLevel
和 Discontinued
BoundFields,并重命名和重新格式化其余的 BoundFields。 我还清除了 Width
and Height
设置。 由于 DetailsView 仅显示一条记录,因此我们需要启用分页,以便允许最终用户查看所有产品。 通过选中 DetailsView 的智能标记中的 Enable Paging 复选框来执行此作。
图 1:选中 DetailsView 智能标记中的 “启用分页 ”复选框 (单击以查看全尺寸图像)
进行这些更改后,DetailsView 标记将为:
<asp:DetailsView ID="DetailsView1" runat="server" AllowPaging="True"
AutoGenerateRows="False" DataKeyNames="ProductID"
DataSourceID="ObjectDataSource1" EnableViewState="False">
<Fields>
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="CategoryName" HeaderText="Category"
ReadOnly="True" SortExpression="CategoryName" />
<asp:BoundField DataField="SupplierName" HeaderText="Supplier"
ReadOnly="True" SortExpression="SupplierName" />
<asp:BoundField DataField="QuantityPerUnit"
HeaderText="Qty/Unit" SortExpression="QuantityPerUnit" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price"
HtmlEncode="False" SortExpression="UnitPrice" />
</Fields>
</asp:DetailsView>
请花点时间在浏览器中测试此页面。
图 2:DetailsView 控件一次显示一个产品 (单击以查看全尺寸图像)
第 2 步:以编程方式确定 DataBound 事件处理程序中数据的值
为了以粗体斜体显示价值超过 75.00 美元的产品 UnitPrice
的价格,我们首先需要能够以编程方式确定 UnitPrice
该值。 对于 DetailsView,这可以在事件处理程序中 DataBound
完成。 要创建事件处理程序,请单击 Designer 中的 DetailsView,然后导航到 Properties 窗口。 如果它不可见,请按 F4 调出它,或者转到 View 菜单并选择 Properties Window 菜单选项。 在 Properties 窗口中,单击闪电图标以列出 DetailsView 的事件。 接下来,双击事件 DataBound
或键入要创建的事件处理程序的名称。
图 3:为 DataBound
事件创建事件处理程序
这样做将自动创建事件处理程序,并带您到已添加事件处理程序的代码部分。 此时您将看到:
protected void ExpensiveProductsPriceInBoldItalic_DataBound(object sender, EventArgs e)
{
}
绑定到 DetailsView 的数据可以通过属性 DataItem
进行访问。 回想一下,我们正在将控件绑定到强类型 DataTable,该 DataTable 由一组强类型 DataRow 实例组成。 当 DataTable 绑定到 DetailsView 时,DataTable 中的第一个 DataRow 将分配给 DetailsView 的属性 DataItem
。 具体而言, DataItem
将为该属性分配一个 DataRowView
对象。 我们可以使用 DataRowView
's Row
属性来访问底层 DataRow 对象,它实际上是一个 ProductsRow
实例。 一旦我们有了这个 ProductsRow
实例,我们就可以通过简单地检查对象的属性值来做出决定。
下面的代码说明了如何确定绑定到 DetailsView 控件的值 UnitPrice
是否大于 $75.00:
protected void ExpensiveProductsPriceInBoldItalic_DataBound(object sender, EventArgs e)
{
// Get the ProductsRow object from the DataItem property...
Northwind.ProductsRow product = (Northwind.ProductsRow)
((DataRowView)ExpensiveProductsPriceInBoldItalic.DataItem).Row;
if (!product.IsUnitPriceNull() && product.UnitPrice > 75m)
{
// TODO: Make the UnitPrice text bold and italic
}
}
注释
由于 UnitPrice
can 在数据库中有一个NULL
值,因此我们首先检查以确保在访问 NULL
'ProductsRow
s 属性之前没有处理UnitPrice
值。 此检查非常重要,因为如果我们尝试在属性具有UnitPrice
值时访问NULL
该属性,则该ProductsRow
对象将引发 StrongTypingException 异常。
步骤 3:在 DetailsView 中设置 UnitPrice 值的格式
此时,我们可以确定绑定到 DetailsView 的值是否 UnitPrice
超过 75.00 美元,但我们尚未了解如何以编程方式相应地调整 DetailsView 的格式。 要修改 DetailsView 中整行的格式,请使用 DetailsViewID.Rows[index]
;要修改特定单元格,请使用 DetailsViewID.Rows[index].Cells[index]
. 一旦我们有了对行或单元格的引用,我们就可以通过设置其样式相关属性来调整其外观。
以编程方式访问行要求您知道该行的索引,该索引从 0 开始。 该 UnitPrice
行是 DetailsView 中的第五行,为其提供索引 4,并使用 ExpensiveProductsPriceInBoldItalic.Rows[4]
. 此时,我们可以使用以下代码以粗体斜体字体显示整行的内容:
ExpensiveProductsPriceInBoldItalic.Rows[4].Font.Bold = true;
ExpensiveProductsPriceInBoldItalic.Rows[4].Font.Italic = true;
但是,这将使标签 (Price) 和值 都 变为粗体和斜体。 如果我们只想将值设为粗体和斜体,则需要将此格式应用于行中的第二个单元格,这可以使用以下方法完成:
ExpensiveProductsPriceInBoldItalic.Rows[4].Cells[1].Font.Bold = true;
ExpensiveProductsPriceInBoldItalic.Rows[4].Cells[1].Font.Italic = true;
由于到目前为止,我们的教程都使用了样式表来保持渲染的标记和样式相关信息之间的清晰分离,因此让我们使用 CSS 类,而不是像上面所示那样设置特定的样式属性。
Styles.css
打开样式表并添加一个以以下定义命名ExpensivePriceEmphasis
的新 CSS 类:
.ExpensivePriceEmphasis
{
font-weight: bold;
font-style: italic;
}
然后,在事件处理程序中 DataBound
,将单元格的属性设置为 CssClass
ExpensivePriceEmphasis
. 下面的代码完整地显示了 DataBound
事件处理程序:
protected void ExpensiveProductsPriceInBoldItalic_DataBound(object sender, EventArgs e)
{
// Get the ProductsRow object from the DataItem property...
Northwind.ProductsRow product = (Northwind.ProductsRow)
((DataRowView)ExpensiveProductsPriceInBoldItalic.DataItem).Row;
if (!product.IsUnitPriceNull() && product.UnitPrice > 75m)
{
ExpensiveProductsPriceInBoldItalic.Rows[4].Cells[1].CssClass =
"ExpensivePriceEmphasis";
}
}
当查看价格低于 75.00 美元的 Chai 时,价格以普通字体显示(参见图 4)。 但是,当查看价格为 97.00 美元的 Mishi Kobe Niku 时,价格以粗体斜体显示(参见图 5)。
图 4:低于 75.00 美元的价格以普通字体显示 (单击以查看全尺寸图像)
图 5:昂贵的产品价格以粗体斜体显示 (单击以查看全尺寸图像)
使用 FormView 控件的事件DataBound
处理程序
确定绑定到 FormView 的基础数据的步骤与 DetailsView 创建 DataBound
事件处理程序、将 DataItem
属性强制转换为绑定到控件的相应对象类型以及确定如何继续的步骤相同。 但是,FormView 和 DetailsView 的不同之处在于其用户界面外观的更新方式。
FormView 不包含任何 BoundFields,因此缺少 Rows
集合。 相反,FormView 由模板组成,这些模板可以包含静态 HTML、Web 控件和数据绑定语法的组合。 调整 FormView 的样式通常涉及调整 FormView 模板中一个或多个 Web 控件的样式。
为了说明这一点,让我们使用 FormView 来列出产品,就像前面的例子一样,但这次我们只显示产品名称和库存量,如果库存量小于或等于 10,则以红色字体显示。
步骤 4:在 FormView 中显示产品信息
将 FormView 添加到 CustomColors.aspx
DetailsView 下的页面,并将其 ID
属性设置为 LowStockedProductsInRed
. 将 FormView 绑定到在上一步中创建的 ObjectDataSource 控件。 这将为 FormView 创建一个 ItemTemplate
、 EditItemTemplate
和 InsertItemTemplate
。
EditItemTemplate
删除 and InsertItemTemplate
并简化 the ItemTemplate
以仅包含 ProductName
and UnitsInStock
值,每个值都位于其各自适当命名的 Label 控件中。 与前面示例中的 DetailsView 一样,还要选中 FormView 的智能标记中的 Enable Paging 复选框。
在这些编辑之后,您的 FormView 的标记应类似于以下内容:
<asp:FormView ID="LowStockedProductsInRed" DataKeyNames="ProductID"
DataSourceID="ObjectDataSource1" AllowPaging="True"
EnableViewState="False" runat="server">
<ItemTemplate>
<b>Product:</b>
<asp:Label ID="ProductNameLabel" runat="server"
Text='<%# Bind("ProductName") %>'>
</asp:Label><br />
<b>Units In Stock:</b>
<asp:Label ID="UnitsInStockLabel" runat="server"
Text='<%# Bind("UnitsInStock") %>'>
</asp:Label>
</ItemTemplate>
</asp:FormView>
请注意,包含 ItemTemplate
:
-
静态 HTML :文本 “Product:” 和 “Units In Stock:” 以及
<br />
和<b>
元素。 -
Web 控件 :两个 Label 控件和
ProductNameLabel
UnitsInStockLabel
. -
数据绑定语法
<%# Bind("ProductName") %>
and<%# Bind("UnitsInStock") %>
语法,用于将这些字段中的值分配给 Label 控件的属性Text
。
步骤 5:以编程方式确定 DataBound 事件处理程序中数据的值
完成 FormView 的标记后,下一步是以编程方式确定该值是否 UnitsInStock
小于或等于 10。 使用 FormView 完成此作的方式与使用 DetailsView 的方式完全相同。 首先为 FormView 的事件创建一个事件 DataBound
处理程序。
图 6:创建 DataBound
事件处理程序
在事件处理程序中,将 FormView 的属性 DataItem
强制转换为实例 ProductsRow
,并确定该值 UnitsInPrice
是否是我们需要以红色字体显示它的值。
protected void LowStockedProductsInRed_DataBound(object sender, EventArgs e)
{
// Get the ProductsRow object from the DataItem property...
Northwind.ProductsRow product = (Northwind.ProductsRow)
((DataRowView)LowStockedProductsInRed.DataItem).Row;
if (!product.IsUnitsInStockNull() && product.UnitsInStock <= 10)
{
// TODO: Make the UnitsInStockLabel text red
}
}
步骤 6:在 FormView 的 ItemTemplate 中设置 UnitsInStockLabel 标签控件的格式
最后一步是将显示的值格式化 UnitsInStock
为红色字体(如果值为 10 或更小)。 为此,我们需要以编程方式访问 UnitsInStockLabel
中的 ItemTemplate
控件并设置其 style 属性,以便其文本显示为红色。 若要访问模板中的 Web 控件,请使用 FindControl("controlID")
如下方法:
WebControlType someName = (WebControlType)FormViewID.FindControl("controlID");
对于我们的示例,我们想要访问一个值为 ID
UnitsInStockLabel
的 Label 控件,因此我们将使用:
Label unitsInStock =
(Label)LowStockedProductsInRed.FindControl("UnitsInStockLabel");
一旦我们有了对 Web 控件的编程引用,我们就可以根据需要修改其与样式相关的属性。 与前面的示例一样,我在名为 Styles.css
中创建LowUnitsInStockEmphasis
了一个 CSS 类。 若要将此样式应用于 Label Web 控件,请相应地设置其 CssClass
属性。
protected void LowStockedProductsInRed_DataBound(object sender, EventArgs e)
{
// Get the ProductsRow object from the DataItem property...
Northwind.ProductsRow product = (Northwind.ProductsRow)
((DataRowView)LowStockedProductsInRed.DataItem).Row;
if (!product.IsUnitsInStockNull() && product.UnitsInStock <= 10)
{
Label unitsInStock =
(Label)LowStockedProductsInRed.FindControl("UnitsInStockLabel");
if (unitsInStock != null)
{
unitsInStock.CssClass = "LowUnitsInStockEmphasis";
}
}
}
注释
在 DetailsView 或 GridView 控件中使用 FindControl("controlID")
时,也可以使用用于以编程方式访问 Web 控件并设置其样式相关属性的模板格式设置模板格式的语法。 我们将在下一个教程中研究 TemplateFields。
图 7 显示了查看值大于 10 的产品 UnitsInStock
时的 FormView,而图 8 中的产品的值小于 10。
图 7:对于库存量足够大的产品,不应用自定义格式 (单击可查看全尺寸图像)
图 8:对于值为 10 或更小的产品,库存量编号显示为红色 (单击以查看全尺寸图像)
使用 GridView 的事件进行格式设置RowDataBound
前面我们研究了 DetailsView 和 FormView 控件在数据绑定过程中执行的步骤顺序。 让我们再次回顾一下这些步骤。
- 数据 Web 控件的事件
DataBinding
触发。 - 数据将绑定到数据 Web 控件。
- 数据 Web 控件的事件
DataBound
触发。
这三个简单的步骤对于 DetailsView 和 FormView 来说已经足够了,因为它们只显示一条记录。 对于 GridView,它显示绑定到它 的所有 记录(而不仅仅是第一个),步骤 2 稍微复杂一些。
在步骤 2 中,GridView 枚举数据源,并为每个记录创建一个 GridViewRow
实例并将当前记录绑定到该实例。
GridViewRow
对于添加到 GridView 的每个事件,将引发两个事件:
-
RowCreated
创建后GridViewRow
触发 -
RowDataBound
在当前记录绑定到GridViewRow
后触发。
因此,对于 GridView,以下步骤序列可以更准确地描述数据绑定:
触发 GridView 的事件
DataBinding
。数据绑定到 GridView。
对于数据源中的每条记录
- 创建
GridViewRow
对象 -
RowCreated
触发事件 - 将记录绑定到
GridViewRow
-
RowDataBound
触发事件 - 向
GridViewRow
集合添加Rows
- 创建
触发 GridView 的事件
DataBound
。
要自定义 GridView 各个记录的格式,我们需要为 RowDataBound
事件创建一个事件处理程序。 为了说明这一点,让我们将 GridView 添加到列出每个产品的名称、类别和价格的 CustomColors.aspx
页面,以黄色背景色突出显示价格低于 10.00 美元的那些产品。
步骤 7:在 GridView 中显示产品信息
在上一个示例中的 FormView 下添加一个 GridView,并将其 ID
属性设置为 HighlightCheapProducts
. 由于我们已经有一个返回页面上所有产品的 ObjectDataSource,因此请将 GridView 绑定到它。 最后,编辑 GridView 的 BoundFields,使其仅包含产品的名称、类别和价格。 进行这些编辑后,GridView 的标记应如下所示:
<asp:GridView ID="HighlightCheapProducts" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ObjectDataSource1"
EnableViewState="False" runat="server">
<Columns>
<asp:BoundField DataField="ProductName" HeaderText="Product"
SortExpression="ProductName" />
<asp:BoundField DataField="CategoryName" HeaderText="Category"
ReadOnly="True" SortExpression="CategoryName" />
<asp:BoundField DataField="UnitPrice" DataFormatString="{0:c}"
HeaderText="Price"
HtmlEncode="False" SortExpression="UnitPrice" />
</Columns>
</asp:GridView>
图 9 显示了通过浏览器查看时我们到这一点的进展。
图 9:GridView 列出每个产品的名称、类别和价格 (单击以查看全尺寸图像)
步骤 8:以编程方式确定 RowDataBound 事件处理程序中数据的值
当 绑定到 ProductsDataTable
GridView 时,将枚举其ProductsRow
实例,并为每个ProductsRow
GridViewRow
实例创建一个。
GridViewRow
的 DataItem
属性分配给 particular ProductRow
,之后引发 GridView 的事件RowDataBound
处理程序。 要确定 UnitPrice
绑定到 GridView 的每个产品的值,我们需要为 GridView 的事件 RowDataBound
创建一个事件处理程序。 在这个事件处理程序中, UnitPrice
我们可以检查当前 GridViewRow
行的值并为该行做出格式化决定。
可以使用与 FormView 和 DetailsView 相同的一系列步骤创建此事件处理程序。
图 10:为 GridView 的事件 RowDataBound
创建事件处理程序
以这种方式创建事件处理程序将导致以下代码自动添加到 ASP.NET 页面的代码部分:
protected void HighlightCheapProducts_RowDataBound(object sender, GridViewRowEventArgs e)
{
}
RowDataBound
当事件触发时,事件处理程序将作为其第二个参数传递一个 类型的GridViewRowEventArgs
对象,该对象具有名为 Row
的属性。 此属性返回对刚刚数据绑定的 的 GridViewRow
引用。 要访问 ProductsRow
绑定到 的 GridViewRow
实例,我们使用 DataItem
属性,如下所示:
protected void HighlightCheapProducts_RowDataBound(object sender, GridViewRowEventArgs e)
{
// Get the ProductsRow object from the DataItem property...
Northwind.ProductsRow product = (Northwind.ProductsRow)
((System.Data.DataRowView)e.Row.DataItem).Row;
if (!product.IsUnitPriceNull() && product.UnitPrice < 10m)
{
// TODO: Highlight the row yellow...
}
}
使用 RowDataBound
事件处理程序时,请务必记住,GridView 由不同类型的行组成,并且此事件会针对 所有 行类型触发。 的类型 GridViewRow
可以由其 RowType
属性确定,并且可以具有以下可能的值之一:
-
DataRow
绑定到 GridView 的DataSource
-
EmptyDataRow
如果 GridView 的DataSource
为空,则显示的行 -
Footer
页脚行;如果 GridView 的属性ShowFooter
设置为true
-
Header
标题行;如果 GridView 的 ShowHeader 属性设置为true
(默认值),则显示 -
Pager
对于实现分页的 GridView,显示分页接口的行 -
Separator
不用于 GridView,但由RowType
DataList 和 Repeater 控件的属性使用,这两个数据 Web 控件我们将在将来的教程中讨论
EmptyDataRow
由于 、 Header
、 Footer
和 Pager
行 未与DataSource
记录关联,因此它们将始终具有null
其DataItem
属性的值。 因此,在尝试使用 current GridViewRow
的 ' DataItem
s 属性之前,我们首先必须确保我们正在处理 DataRow
. 这可以通过检查 GridViewRow
's RowType
属性来实现,如下所示:
protected void HighlightCheapProducts_RowDataBound(object sender, GridViewRowEventArgs e)
{
// Make sure we are working with a DataRow
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Get the ProductsRow object from the DataItem property...
Northwind.ProductsRow product = (Northwind.ProductsRow)
((System.Data.DataRowView)e.Row.DataItem).Row;
if (!product.IsUnitPriceNull() && product.UnitPrice < 10m)
{
// TODO: Highlight row yellow...
}
}
}
第 9 步:当 UnitPrice 值小于 10.00 USD 时突出显示黄色行
最后一步是,如果GridViewRow
该行的值小于 10.00 USD,则以编程方式突出显示整个UnitPrice
。 访问 GridView 的行或单元格的语法与使用 DetailsView GridViewID.Rows[index]
访问整行以 GridViewID.Rows[index].Cells[index]
访问特定单元格的语法相同。 但是,当事件处理程序触发时 RowDataBound
,数据绑定 GridViewRow
尚未添加到 GridView 的集合 Rows
中。 因此,您无法使用 Rows 集合从GridViewRow
事件处理程序访问当前RowDataBound
实例。
我们可以使用 ,而不是 GridViewID.Rows[index]
,在事件处理程序中GridViewRow
引用RowDataBound
当前e.Row
实例。 也就是说,为了从事件处理程序中突出显示当前 GridViewRow
实例 RowDataBound
,我们将使用:
e.Row.BackColor = System.Drawing.Color.Yellow;
与其直接设置 GridViewRow
's BackColor
属性,不如坚持使用 CSS 类。 我创建了一个名为 AffordablePriceEmphasis
的 CSS 类,该类将背景颜色设置为黄色。 已完成 RowDataBound
的事件处理程序如下:
protected void HighlightCheapProducts_RowDataBound(object sender, GridViewRowEventArgs e)
{
// Make sure we are working with a DataRow
if (e.Row.RowType == DataControlRowType.DataRow)
{
// Get the ProductsRow object from the DataItem property...
Northwind.ProductsRow product = (Northwind.ProductsRow)
((System.Data.DataRowView)e.Row.DataItem).Row;
if (!product.IsUnitPriceNull() && product.UnitPrice < 10m)
{
e.Row.CssClass = "AffordablePriceEmphasis";
}
}
}
图 11:最实惠的产品以黄色突出显示 (单击以查看全尺寸图像)
概要
在本教程中,我们了解了如何根据绑定到控件的数据设置 GridView、DetailsView 和 FormView 的格式。 为了实现这一点,我们为 or DataBound
事件创建了一个事件处理程序RowDataBound
,其中检查了底层数据,并在需要时进行了格式更改。 要访问绑定到 DetailsView 或 FormView 的数据,我们在事件处理程序中使用该DataItem
属性;对于 GridView,每个DataBound
实例的属性GridViewRow
都包含绑定到该行的数据,该数据在事件处理程序中可用DataItem
RowDataBound
。
用于以编程方式调整数据 Web 控件格式的语法取决于 Web 控件以及要格式化的数据的显示方式。 对于 DetailsView 和 GridView 控件,行和单元格可以通过序号索引访问。 对于使用模板的 FormView, FindControl("controlID")
该方法通常用于从模板中查找 Web 控件。
在下一教程中,我们将了解如何将模板与 GridView 和 DetailsView 一起使用。 此外,我们将看到另一种基于基础数据自定义格式的技术。
快乐编程!
关于作者
斯科特·米切尔,七本 ASP/ASP.NET 书籍的作者和 4GuysFromRolla.com 的创始人,自1998年以来一直在与Microsoft Web 技术合作。 斯科特担任独立顾问、教练和作家。 他的最新书是 《Sams Teach Yourself ASP.NET 2.0 in 24 Hours》。 可以通过 mitchell@4GuysFromRolla.com 联系到他。
特别致谢
本教程系列由许多有用的审阅者审阅。 本教程的主要审阅者是 E.R. Gilmore、Dennis Patterson 和 Dan Jagers。 有兴趣查看即将发布的 MSDN 文章? 如果是这样,请给我写信。mitchell@4GuysFromRolla.com