在 DetailsView 控件中使用 TemplateField (VB)
GridView 提供的相同 TemplateFields 功能也可用于 DetailsView 控件。 在本教程中,我们将使用包含 TemplateFields 的 DetailsView 一次显示一个产品。
简介
与 BoundField、CheckBoxField、HyperLinkField 和其他数据字段控件相比,TemplateField 在呈现数据方面具有更高的灵活性。 在 上一教程中 ,我们了解了如何在 GridView 中使用 TemplateField 来:
- 在一列中显示多个数据字段值。 具体而言,和
FirstName
LastName
字段合并为一个 GridView 列。 - 使用备用 Web 控件来表示数据字段值。 我们了解了如何使用 Calendar 控件显示
HiredDate
值。 - 显示基于基础数据的状态信息。 尽管该
Employees
表不包含返回员工在作业中的天数的列,但我们能够使用 TemplateField 和格式设置方法在上一教程的 GridView 示例中显示此类信息。
GridView 提供的相同 TemplateFields 功能也可用于 DetailsView 控件。 在本教程中,我们将使用包含两个 TemplateField 的 DetailsView 一次显示一个产品。 第一个 TemplateField 会将 、 UnitsInStock
和数据UnitsOnOrder
字段合并UnitPrice
为一个 DetailsView 行。 第二个 TemplateField 将显示字段的值Discontinued
,但如果 为 True
,则使用格式设置方法显示“YESDiscontinued
”,否则将显示“NO”。
图 1:两个 TemplateField 用于自定义显示 (单击以查看全尺寸图像)
现在就开始吧!
步骤 1:将数据绑定到 DetailsView
如上一教程中所述,使用 TemplateFields 时,通常最简单的方法是创建仅包含 BoundFields 的 DetailsView 控件,然后添加新的 TemplateFields 或根据需要将现有 BoundField 转换为 TemplateFields。 因此,请首先通过 Designer 将 DetailsView 添加到页面,并将其绑定到返回产品列表的 ObjectDataSource。 这些步骤将为每个产品的非布尔值字段创建带有 BoundFields 的 DetailsView,并为一个布尔值字段创建一个 CheckBoxField, (已停用) 。
打开页面并将DetailsViewTemplateField.aspx
“详细信息”视图从“工具箱”拖到Designer。 从 DetailsView 的智能标记中,选择添加调用 ProductsBLL
类的 GetProducts()
方法的新 ObjectDataSource 控件。
图 2:添加一个新的 ObjectDataSource 控件,该控件调用 GetProducts()
方法 (单击以查看全尺寸图像)
对于此报表, ProductID
请删除 、 SupplierID
、 CategoryID
和 ReorderLevel
BoundFields。 接下来,对 BoundField 进行重新排序, CategoryName
使 和 SupplierName
BoundField 紧跟在 BoundField 之后 ProductName
。 根据需要随意调整 HeaderText
BoundFields 的属性和格式设置属性。 与 GridView 一样,可以通过“字段”对话框执行这些 BoundField 级别的编辑, (单击 DetailsView 的智能标记中的“编辑字段”链接) 或通过声明性语法进行访问。 最后,清除 DetailsView 的 Height
和 Width
属性值,以便根据显示的数据扩展 DetailsView 控件,并检查智能标记中的“启用分页”复选框。
进行这些更改后,DetailsView 控件的声明性标记应如下所示:
<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False"
DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True"
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" HeaderText="Price"
SortExpression="UnitPrice" />
<asp:BoundField DataField="UnitsInStock"
HeaderText="Units In Stock" SortExpression="UnitsInStock" />
<asp:BoundField DataField="UnitsOnOrder"
HeaderText="Units On Order" SortExpression="UnitsOnOrder" />
<asp:CheckBoxField DataField="Discontinued"
HeaderText="Discontinued" SortExpression="Discontinued" />
</Fields>
</asp:DetailsView>
花点时间通过浏览器查看页面。 此时,应会看到一个产品 (Chai) 列出,其中行显示产品的名称、类别、供应商、价格、库存单位、订单数量及其停产状态。
图 3:使用一系列 BoundFields 显示产品的详细信息 (单击查看全尺寸图像)
步骤 2:将“价格”、“库存单位”和“订单单位”合并为一行
DetailsView 有一行用于 UnitPrice
、 UnitsInStock
和 UnitsOnOrder
字段。 可以通过添加新 TemplateField 或将现有 UnitPrice
、 UnitsInStock
和 UnitsOnOrder
BoundField 之一转换为 TemplateField,将这些数据字段合并为单个行。 虽然我个人更喜欢转换现有的 BoundField,但让我们通过添加新的 TemplateField 来练习。
首先,单击 DetailsView 的智能标记中的“编辑字段”链接,打开“字段”对话框。 接下来,添加新的 TemplateField 并将其 HeaderText
属性设置为“Price and Inventory”,并移动新的 TemplateField,使其位于 BoundField 上方 UnitPrice
。
图 4:将新 TemplateField 添加到 DetailsView 控件 (单击以查看全尺寸图像)
由于此新 TemplateField 将包含 、 和 UnitsOnOrder
BoundFields 中UnitPrice
UnitsInStock
当前显示的值,因此让我们删除它们。
此步骤的最后一个任务是定义 ItemTemplate
Price 和 Inventory TemplateField 的标记,这可以通过Designer中的 DetailsView 模板编辑界面来完成,也可以手动通过控件的声明性语法来完成。 与 GridView 一样,可以通过单击智能标记中的“编辑模板”链接来访问 DetailsView 的模板编辑界面。 在此处,可以从下拉列表选择要编辑的模板,然后从“工具箱”添加任何 Web 控件。
在本教程中,首先将 Label 控件添加到 Price 和 Inventory TemplateField 的 ItemTemplate
。 接下来,单击 Label Web 控件的智能标记中的“编辑数据绑定”链接,并将 Text
属性绑定到 字段 UnitPrice
。
图 5:将标签的 Text
属性绑定到 UnitPrice
数据字段 (单击以查看全尺寸图像)
将价格格式设置为货币
添加此项后,标签 Web 控件“价格”和“库存模板字段”现在仅显示所选产品的价格。 图 6 显示了通过浏览器查看到目前为止的进度的屏幕截图。
图 6:“价格和库存模板”字段显示“价格” (单击以查看全尺寸图像)
请注意,产品的价格未格式化为货币。 使用 BoundField 时,通过将 属性设置为 ,DataFormatString
{0:formatSpecifier}
将 属性设置为 HtmlEncode
False
可以进行格式设置。 但是,对于 TemplateField,任何格式设置说明都必须在数据绑定语法中指定,或者通过使用在应用程序代码 ((如 ASP.NET 页的代码隐藏类) 中)中定义的格式设置方法。
若要指定标签 Web 控件中使用的数据绑定语法的格式,请从标签的智能标记中单击“编辑数据绑定”链接,返回到“数据绑定”对话框。 可以直接在“格式”下拉列表中键入格式设置说明,也可以选择已定义的格式字符串之一。 与 BoundField 的 DataFormatString
属性一样,使用 指定 {0:formatSpecifier}
格式设置。
对于字段, UnitPrice
请使用指定的货币格式,方法是选择相应的下拉列表值或通过手动键入 {0:C}
。
图 7:将价格格式化为货币 (单击以查看全尺寸图像)
以声明方式将格式规范指示为 或 Eval
方法中的第二个参数Bind
。 刚通过 Designer设置会导致声明性标记中出现以下数据绑定表达式:
<asp:Label ID="Label1" runat="server" Text='<%# Eval("UnitPrice", "{0:C}") %>'/>
将剩余数据字段添加到 TemplateField
此时,我们已在“价格”和“库存模板”字段中显示数据字段并设置了 UnitPrice
格式,但仍需要显示 UnitsInStock
和 UnitsOnOrder
字段。 让我们在价格下方的一行和括号中显示这些内容。 在Designer的模板编辑界面中,可以通过将光标置于模板中并键入要显示的文本来添加此类标记。 或者,可以直接在声明性语法中输入此标记。
添加静态标记、标签 Web 控件和数据绑定语法,使价格和库存模板字段显示价格和库存信息,如下所示:
UnitPrice
(库存/订单中:UnitsInStock / UnitsOnOrder)
执行此任务后,DetailsView 的声明性标记应如下所示:
<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False"
DataKeyNames="ProductID" DataSourceID="ObjectDataSource1" AllowPaging="True"
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:TemplateField HeaderText="Price and Inventory">
<ItemTemplate>
<asp:Label ID="Label1" runat="server"
Text='<%# Eval("UnitPrice", "{0:C}") %>'></asp:Label>
<br />
<strong>
(In Stock / On Order: </strong>
<asp:Label ID="Label2" runat="server"
Text='<%# Eval("UnitsInStock") %>'></asp:Label>
<strong>/</strong>
<asp:Label ID="Label3" runat="server"
Text='<%# Eval("UnitsOnOrder") %>'>
</asp:Label><strong>)</strong>
</ItemTemplate>
</asp:TemplateField>
<asp:CheckBoxField DataField="Discontinued"
HeaderText="Discontinued" SortExpression="Discontinued" />
</Fields>
</asp:DetailsView>
通过这些更改,我们已将价格和库存信息合并到单个 DetailsView 行中。
图 8:价格和库存信息显示在单行 (单击以查看全尺寸图像)
步骤 3:自定义已停用的字段信息
表 Products
的 Discontinued
列是一个位值,指示产品是否已停产。 将 DetailsView (或 GridView) 绑定到数据源控件时,布尔值字段(如 Discontinued
)实现为 CheckBoxFields,而非布尔值字段(如 ProductID
、 ProductName
等)实现为 BoundFields。 如果数据字段的值为 True,则 CheckBoxField 呈现为禁用的复选框,否则将选中该复选框。
与其显示 CheckBoxField,不如显示指示产品是否停产的文本。 为此,我们可以从 DetailsView 中删除 CheckBoxField,然后添加属性设置为 Discontinued
的 DataField
BoundField。 花点时间执行此操作。 此更改后,对于已停用的产品,DetailsView 将显示文本“True”,对于仍处于活动状态的产品,则显示文本“False”。
图 9:字符串 True 和 False 用于显示停用状态 (单击以查看全尺寸图像)
假设我们不希望使用字符串“True”或“False”,而是使用“YES”和“NO”。 可以在 TemplateField 和格式设置方法的帮助下执行此类自定义。 格式设置方法可以采用任意数量的输入参数,但必须将 HTML (作为字符串返回,) 注入到模板中。
将格式设置方法添加到DetailsViewTemplateField.aspx
页面的代码隐藏类中,该类接受DisplayDiscontinuedAsYESorNO
Northwind.ProductsRow
对象作为输入参数并返回字符串。 如上一教程中所述, 必须 将 Protected
此方法标记为 或 Public
才能从模板访问。
Protected Function DisplayDiscontinuedAsYESorNO(discontinued As Boolean) As String
If discontinued Then
Return "YES"
Else
Return "NO"
End If
End Function
此方法检查输入参数 (discontinued
) ,如果为 True
,则返回“YES”,否则返回“NO”。
注意
在上一教程中介绍的格式设置方法中,我们传入了可能包含 NULL
的数据字段,因此需要在访问 EmployeesRow
HiredDate
的 属性之前检查员工的HiredDate
属性值是否具有数据库NULL
值。 此处不需要此类检查,Discontinued
因为该列永远不会分配数据库NULL
值。 此外,这就是为什么 方法可以接受布尔输入参数,而不必接受 ProductsRow
实例或类型的 Object
参数。
完成此格式设置方法后,剩下的就是从 TemplateField 的 ItemTemplate
调用它。 若要创建 TemplateField, Discontinued
请删除 BoundField 并添加新的 TemplateField 或将 Discontinued
BoundField 转换为 TemplateField。 然后,从声明性标记视图中编辑 TemplateField,使其仅包含一个调用 DisplayDiscontinuedAsYESorNO
方法的 ItemTemplate,并传入当前 ProductRow
实例的 Discontinued
属性的值。 这可以通过 方法进行访问 Eval
。 具体而言,TemplateField 的标记应如下所示:
<asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
<ItemTemplate>
<%#DisplayDiscontinuedAsYESorNO(Convert.ToBoolean(Eval("Discontinued")))%>
</ItemTemplate>
</asp:TemplateField>
这将导致在 DisplayDiscontinuedAsYESorNO
呈现 DetailsView 时调用 方法,并 ProductRow
传入实例的值 Discontinued
。 Eval
由于 方法返回类型的Object
值,但DisplayDiscontinuedAsYESorNO
该方法需要类型的Boolean
输入参数,因此我们将方法返回值强制转换为 Eval
Boolean
。 然后,方法 DisplayDiscontinuedAsYESorNO
将返回“YES”或“NO”,具体取决于它收到的值。 返回的值是此 DetailsView 行中显示的值, (请参阅图 10) 。
图 10:“是”或“否”值现在显示在“已停用的行” (单击以查看全尺寸图像)
总结
与其他字段控件相比,DetailsView 控件中的 TemplateField 在显示数据方面具有更高的灵活性,非常适合以下情况:
- 需要在一个 GridView 列中显示多个数据字段
- 最好使用 Web 控件而不是纯文本来表示数据
- 输出取决于基础数据,例如显示元数据或重新格式化数据
虽然 TemplateFields 允许在呈现 DetailsView 的基础数据时具有更大的灵活性,但 DetailsView 输出仍然有点开箱,因为每个字段都呈现为 HTML <table>
中的一行。
FormView 控件在配置呈现的输出方面提供了更大的灵活性。 FormView 不包含字段,而只包含一系列 (ItemTemplate
、、 EditItemTemplate
HeaderTemplate
等) 模板。 在下一教程中,我们将了解如何使用 FormView 实现对呈现布局的更多控制。
编程快乐!
关于作者
斯科特·米切尔是七本 ASP/ASP.NET 书籍的作者和 4GuysFromRolla.com 的创始人,自 1998 年以来一直在使用 Microsoft Web 技术。 Scott 担任独立顾问、培训师和作家。 他的最新一本书是 山姆斯在 24 小时内 ASP.NET 2.0。 可以在 上mitchell@4GuysFromRolla.com联系他,也可以通过他的博客(可在 中找到http://ScottOnWriting.NET)。
特别感谢
本教程系列由许多有用的审阅者审阅。 本教程的首席审阅者是 Dan Jagers。 有兴趣查看我即将发布的 MSDN 文章? 如果是,请在 处mitchell@4GuysFromRolla.com放置一行。
反馈
https://aka.ms/ContentUserFeedback。
即将发布:在整个 2024 年,我们将逐步淘汰作为内容反馈机制的“GitHub 问题”,并将其取代为新的反馈系统。 有关详细信息,请参阅:提交和查看相关反馈