作者 :斯科特·米切尔
在本教程中,我们将逐步讲解如何设置 DataList 和 Repeater 控件的外观格式的示例,无论是在模板中使用格式设置函数还是处理 DataBound 事件。
介绍
正如我们在前面的教程中看到的那样,DataList 提供了许多影响其外观的样式相关属性。 具体而言,我们了解了如何将默认 CSS 类分配给 DataList s HeaderStyle
、 ItemStyle
、 AlternatingItemStyle
和 SelectedItemStyle
属性。 除了这四个属性之外,DataList 还包括一些其他与样式相关的属性,例如 Font
, ForeColor
和 BackColor
,等等 BorderWidth
。 Repeater 控件不包含任何与样式相关的属性。 任何此类样式设置都必须直接在 Repeater 模板中的标记中进行。
不过,数据的格式通常取决于数据本身。 例如,在列出产品时,我们可能希望在产品停用时以浅灰色字体颜色显示产品信息,或者如果产品为零,则可能需要突出显示 UnitsInStock
该值。 正如我们在前面的教程中看到的那样,GridView、DetailsView 和 FormView 提供了两种不同的方法来根据数据设置其外观格式:
-
该
DataBound
事件 为相应的DataBound
事件创建事件处理程序,该事件处理程序在数据绑定到每个项后触发(对于 GridView,它是RowDataBound
事件;对于 DataList 和 Repeater,它是事件ItemDataBound
)。 在该事件处理程序中,可以检查刚刚绑定的数据并设置决策的格式。 我们在 “基于数据自定义格式设置” 教程中介绍了此方法。 - 模板中的格式化函数 在 DetailsView 或 GridView 控件中使用 TemplateFields 或在 FormView 控件中使用模板时,我们可以向 ASP.NET 页的代码隐藏类、业务逻辑层或任何其他可从 Web 应用程序访问的类库中添加格式化函数。 此格式设置函数可以接受任意数量的输入参数,但必须返回 HTML 才能在模板中呈现。 首次在 GridView 控件教程的 Using TemplateFields 中 检查格式化函数。
DataList 和 Repeater 控件提供了这两种格式设置技术。 在本教程中,我们将逐步介绍使用这两种控件的方法的示例。
使用ItemDataBound
事件处理器
当数据绑定到 DataList 时,无论是通过数据源控件,还是通过以编程方式将数据分配给控件的 DataSource
属性并调用其 DataBind()
方法,DataList 的 DataBinding
事件将触发,然后枚举数据源,并将每个数据记录绑定到 DataList。 对于数据源中的每个记录,DataList 将创建一个 DataListItem
对象,然后绑定到当前记录。 在此过程中,DataList 会引发两个事件:
-
ItemCreated
创建后DataListItem
触发 -
ItemDataBound
在当前记录绑定到DataListItem
后触发
以下步骤概述了 DataList 控件的数据绑定过程。
DataList
DataBinding
事件触发数据被绑定到 DataList
对于数据源中的每条记录
- 创建
DataListItem
对象 -
ItemCreated
触发事件 - 将记录绑定到
DataListItem
-
ItemDataBound
启动事件 - 向
Items
集合添加DataListItem
- 创建
将数据绑定到 Repeater 控件时,它会执行完全相同的步骤序列。 唯一的区别在于,Repeater 使用的是RepeaterItem
而不是创建DataListItem
实例。
注释
精明的读者可能注意到,当 DataList 和 Repeater 绑定到数据时与 GridView 绑定到数据时的步骤序列之间存在细微的异常。 在数据绑定过程的结尾,GridView 将 DataBound
引发事件;但是,DataList 和 Repeater 控件都没有此类事件。 这是因为 DataList 和 Repeater 控件是在 ASP.NET 1.x 时间范围内创建的,在前级和后级事件处理程序模式变得常见之前。
与 GridView 一样,基于数据的格式化的一个选项是为事件创建事件处理程序 ItemDataBound
。 此事件处理程序将检查刚刚绑定到 DataListItem
或 RepeaterItem
的数据,并根据需要影响控件的格式。
对于 DataList 控件,可以使用与样式相关的属性(包括标准样式,如 DataListItem
、Font
、ForeColor
、BackColor
、CssClass
等)来实现整个项目的格式更改。 若要影响 DataList 模板中特定 Web 控件的格式设置,我们需要以编程方式访问和修改这些 Web 控件的样式。 我们在“基于数据的自定义格式设定”教程中已看到如何实现这一点。 与 Repeater 控件一样,RepeaterItem
类没有与样式相关的属性;因此,必须通过在 ItemDataBound
事件处理程序中以编程方式访问和更新模板内的 Web 控件,来完成所有与样式相关的更改。
ItemDataBound
由于 DataList 和 Repeater 的格式设置技术几乎完全相同,我们的示例将重点介绍如何使用 DataList。
步骤 1:在 DataList 中显示产品信息
在担心格式设置之前,让我们先创建一个使用 DataList 显示产品信息的页面。 在 上一教程 中,我们创建了一个 DataList,其中 ItemTemplate
显示了每个产品名称、类别、供应商、每个单位的数量和价格。 让我们在本教程中在此处重复此功能。 为此,可以从头开始重新创建 DataList 及其 ObjectDataSource,也可以从上一教程Basics.aspx
()中创建的页面复制这些控件,并将其粘贴到本教程的页面(Formatting.aspx
)。
从Basics.aspx
复制出 DataList 和 ObjectDataSource 功能到Formatting.aspx
后,请花些时间将 DataList 的属性ID
从DataList1
更改为更具描述性的ItemDataBoundFormattingExample
。 接下来,在浏览器中查看 DataList。 如图 1 所示,每个产品之间的唯一格式差异是背景色交替。
图 1:产品列在 DataList 控件中(单击以查看全尺寸图像)
在本教程中,让我们设置 DataList 的格式,以便任何价格低于 $20.00 的产品的名称和单价都突出显示为黄色。
步骤 2:以编程方式确定 ItemDataBound 事件处理程序中的数据值
由于只有价格低于 $20.00 的产品才会应用自定义格式,因此我们必须能够确定每个产品的价格。 将数据绑定到 DataList 时,DataList 会枚举其数据源中的记录,并为每个记录创建一个 DataListItem
实例,将数据源记录绑定到该 DataListItem
记录。 将特定记录的数据绑定到当前 DataListItem
对象后,将触发 DataList s ItemDataBound
事件。 我们可以为此事件创建事件处理程序,以检查当前 DataListItem
数据值,并根据这些值进行任何必要的格式更改。
为 DataList 创建事件 ItemDataBound
并添加以下代码:
protected void ItemDataBoundFormattingExample_ItemDataBound
(object sender, DataListItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
// Programmatically reference the ProductsRow instance bound
// to this DataListItem
Northwind.ProductsRow product =
(Northwind.ProductsRow)((System.Data.DataRowView)e.Item.DataItem).Row;
// See if the UnitPrice is not NULL and less than $20.00
if (!product.IsUnitPriceNull() && product.UnitPrice < 20)
{
// TODO: Highlight the product's name and price
}
}
}
虽然 DataList 事件处理程序 ItemDataBound
背后的概念和语义与 GridView 事件处理程序 RowDataBound
在 自定义格式基于数据 教程中使用的概念和语义相同,但语法略有不同。
ItemDataBound
事件触发时,刚绑定到数据的DataListItem
通过e.Item
传递到相应的事件处理程序中,而不是像GridView的RowDataBound
事件处理程序通过e.Row
一样。 DataList 的 ItemDataBound
事件处理程序会针对添加到 DataList 的每一行触发,其中包括页眉行、页脚行和分隔符行。 但是,产品信息仅绑定到数据行。 因此,使用 ItemDataBound
事件检查绑定到 DataList 的数据时,首先需要确保我们正在处理一个数据项。 这可以通过检查 DataListItem
s ItemType
属性来实现,该属性可以具有以下 八个值之一:
AlternatingItem
EditItem
Footer
Header
Item
Pager
SelectedItem
Separator
Item
和AlternatingItem``DataListItem
共同组成DataList的数据项。 假设我们正在处理Item
或AlternatingItem
,我们可以访问绑定到当前DataListItem
的实际ProductsRow
实例。
DataListItem
s DataItem
属性包含对DataRowView
对象的引用,该Row
对象的属性提供对实际ProductsRow
对象的引用。
接下来,检查 ProductsRow
实例 UnitPrice
的属性。 由于 Products 表的 UnitPrice
字段允许 NULL
值,因此在尝试访问 UnitPrice
属性之前,应首先使用 IsUnitPriceNull()
方法检查它是否具有 NULL
的值。
UnitPrice
如果值不是NULL
,我们检查该值是否小于 20.00 美元。 如果它确实低于 $20.00,则我们需要应用自定义格式。
步骤 3:突出显示产品名称和价格
一旦我们知道产品的价格低于 20.00 美元,剩下的就是突出其名称和价格。 为此,必须首先以编程方式引用显示产品名称和价格的 ItemTemplate
Label 控件。 接下来,我们需要让它们显示黄色背景。 可以通过直接修改标签 BackColor
属性来应用此格式信息(LabelID.BackColor = Color.Yellow
理想情况下,所有与显示相关的事项都应通过级联样式表来表示。 事实上,我们已经有一个样式表,它提供了Styles.css
- AffordablePriceEmphasis
中所需的格式。这些格式是在基于数据的自定义格式教程中创建并讨论的。
若要应用格式设置,只需将两个标签 Web 控件 CssClass
属性设置为 AffordablePriceEmphasis
,如以下代码所示:
// Highlight the product name and unit price Labels
// First, get a reference to the two Label Web controls
Label ProductNameLabel = (Label)e.Item.FindControl("ProductNameLabel");
Label UnitPriceLabel = (Label)e.Item.FindControl("UnitPriceLabel");
// Next, set their CssClass properties
if (ProductNameLabel != null)
ProductNameLabel.CssClass = "AffordablePriceEmphasis";
if (UnitPriceLabel != null)
UnitPriceLabel.CssClass = "AffordablePriceEmphasis";
完成ItemDataBound
事件处理程序后,在浏览器中重新访问Formatting.aspx
页面。 如图 2 所示,价格低于 20.00 美元的这些产品的名称和价格都突出显示。
图 2:突出显示的这些产品小于 20.00 美元(单击可查看全尺寸图像)
注释
由于 DataList 呈现为 HTML <table>
,因此其 DataListItem
实例具有与样式相关的属性,这些属性可以设置为将特定样式应用于整个项。 例如,如果我们想要在价格低于 $20.00 时突出显示 整个 项目黄色,我们可以替换引用标签的代码,并使用以下代码行设置其 CssClass
属性: e.Item.CssClass = "AffordablePriceEmphasis"
(请参阅图 3)。
RepeaterItem
但是,构成 Repeater 控件的 s 不提供此类样式级别属性。 因此,将自定义格式应用于 Repeater 需要将样式属性应用于 Repeater 模板中的 Web 控件,就像我们在图 2 中所做的那样。
图 3:20.00 美元以下产品的整个产品项突出显示(单击以查看全尺寸图像)
使用模板中的格式设置函数
在 GridView 控件中的 Using TemplateFields 教程中,我们了解了如何使用 GridView TemplateField 中的格式设置函数基于绑定到 GridView 行的数据应用自定义格式。 格式设置函数是一种方法,可以从模板中调用,并返回用于替代其位置的 HTML。 格式设置函数可以存放在 ASP.NET 页的代码隐藏类中,也可以集中到 App_Code
文件夹中的类文件或单独的类库项目中。 如果打算在多个 ASP.NET 页或其他 ASP.NET Web 应用程序中使用相同的格式设置函数,则可以将格式设置函数移出 ASP.NET 页面的代码隐藏类。
为了演示格式设置函数,让我们让产品信息包括产品名称旁的文本 [DISCONTINUED](如果已停用)。 此外,如果价格小于 20.00 美元(正如我们在 ItemDataBound
事件处理程序示例中所做的那样),让我们将价格突出显示为黄色;如果价格为 20.00 美元或更高,则不要显示实际价格,而是文本,请调用价目表。 图 4 显示了应用了这些格式规则的产品列表的屏幕截图。
图 4:对于昂贵的产品,价格将替换为文本,请调用价目表(单击以查看全尺寸图像)
步骤 1:创建格式设置函数
对于此示例,我们需要两个格式化函数:一个用于显示产品名称以及文本 “[已停产]”(如果需要),另一个则在价格低于 $20.00 时显示突出显示价格,否则显示“请致电询价”。 让我们在 ASP.NET 页面的代码隐藏类中创建这些函数,并将其命名为DisplayProductNameAndDiscontinuedStatus
和DisplayPrice
。 这两种方法都需要返回 HTML 才能呈现为字符串,并且都需要标记为 Protected
(或 Public
) 才能从 ASP.NET 页的声明性语法部分调用。 这两种方法的代码如下:
protected string DisplayProductNameAndDiscontinuedStatus
(string productName, bool discontinued)
{
// Return just the productName if discontinued is false
if (!discontinued)
return productName;
else
// otherwise, return the productName appended with the text "[DISCONTINUED]"
return string.Concat(productName, " [DISCONTINUED]");
}
protected string DisplayPrice(Northwind.ProductsRow product)
{
// If price is less than $20.00, return the price, highlighted
if (!product.IsUnitPriceNull() && product.UnitPrice < 20)
return string.Concat("<span class=\"AffordablePriceEmphasis\">",
product.UnitPrice.ToString("C"), "</span>");
else
// Otherwise return the text, "Please call for a price quote"
return "<span>Please call for a price quote</span>";
}
请注意,DisplayProductNameAndDiscontinuedStatus
该方法接受数据字段的值productName
discontinued
作为标量值,而DisplayPrice
该方法接受ProductsRow
实例(而不是unitPrice
标量值)。 任一方法都可能起作用;但是,如果格式功能处理可包含数据库 NULL
值的标量值(例如 UnitPrice
;ProductName
和 Discontinued
都不允许 NULL
值),则必须特别注意处理这些标量输入。
具体而言,输入参数的类型必须为类型 Object
,因为传入值可能是 DBNull
实例而不是预期的数据类型。 此外,必须进行检查以确定传入值是否为数据库 NULL
值。 也就是说,如果我们希望 DisplayPrice
该方法接受价格作为标量值,则必须使用以下代码:
protected string DisplayPrice(object unitPrice)
{
// If price is less than $20.00, return the price, highlighted
if (!Convert.IsDBNull(unitPrice) && ((decimal) unitPrice) < 20)
return string.Concat("<span class=\"AffordablePriceEmphasis\">",
((decimal) unitPrice).ToString("C"), "</span>");
else
// Otherwise return the text, "Please call for a price quote"
return "<span>Please call for a price quote</span>";
}
请注意,unitPrice
输入参数是Object
类型,并且条件语句已被修改,以确定unitPrice
是否是DBNull
。 此外,由于 unitPrice
输入参数作为 Object
传入,因此必须将其强制转换为十进制值。
步骤 2:从 DataList s ItemTemplate 调用格式设置函数
将格式化函数添加到 ASP.NET 页的代码隐藏类中后,剩余的一切就是从 DataList s ItemTemplate
调用这些格式设置函数。 若要从模板调用格式设置函数,请将函数调用置于数据绑定语法中:
<%# MethodName(inputParameter1, inputParameter2, ...) %>
在ItemTemplate
DataList 中,ProductNameLabel
标签 Web 控件当前通过将其Text
属性设置为<%# Eval("ProductName") %>
的结果来显示产品名称。 为了使其显示名称加上文本 [DISCONTINUED](如果需要),请更新声明性语法,以便改为将 Text
属性的值赋予 DisplayProductNameAndDiscontinuedStatus
方法。 在进行此操作时,必须使用Eval("columnName")
语法传入产品名称和停用的值。
Eval
返回的值是Object
类型,但DisplayProductNameAndDiscontinuedStatus
方法期望的输入参数为String
和Boolean
类型;因此,必须将Eval
方法返回的值类型转换为预期的输入参数类型,如下所示:
<h4>
<asp:Label ID="ProductNameLabel" runat="server"
Text='<%# DisplayProductNameAndDiscontinuedStatus((string) Eval("ProductName"),
(bool) Eval("Discontinued")) %>'>
</asp:Label>
</h4>
为了显示价格,我们只需将 UnitPriceLabel
Label的 Text
属性设置为 DisplayPrice
方法返回的值,就像我们之前为显示产品名称和 [DISCONTINUED] 文本所做的一样。 但是,我们改为传入整个ProductsRow
实例,而不是作为UnitPrice
标量输入参数传入:
<asp:Label ID="UnitPriceLabel" runat="server"
Text='<%# DisplayPrice((Northwind.ProductsRow)
((System.Data.DataRowView) Container.DataItem).Row) %>'>
</asp:Label>
调用格式设置函数后,请花点时间在浏览器中查看进度。 你的屏幕应类似于图 5,其中停产的产品包括文本“[DISCONTINUED]”,而那些价格超过 20.00 美元的产品,其价格被替换为文本“请致电询价”。
图 5:对于昂贵的产品,价格将替换为文本,请调用价目表(单击以查看全尺寸图像)
概要
可以使用两种方法根据数据设置 DataList 或 Repeater 控件的内容的格式。 第一种技术是为ItemDataBound
事件创建事件处理程序,该事件在数据源中的每个记录绑定到新的DataListItem
或RepeaterItem
时触发。 在 ItemDataBound
事件处理程序中,可以检查当前项的数据,然后可以将格式应用于模板的内容,或者针对 DataListItem
将格式应用于整个项本身。
或者,可以通过格式设置函数实现自定义格式设置。 格式化函数是可以从 DataList 或 Repeater 模板调用的方法,该方法返回要在其位置输出的 HTML。 通常,格式设置函数返回的 HTML 是由当前项所绑定的值决定的。 这些值可以作为标量值传递到格式设置函数中,也可以通过传入绑定到项(如 ProductsRow
实例)的整个对象来传递。
快乐编程!
关于作者
斯科特·米切尔,七本 ASP/ASP.NET 书籍的作者和 4GuysFromRolla.com 的创始人,自1998年以来一直在与Microsoft Web 技术合作。 斯科特担任独立顾问、教练和作家。 他的最新书是 《Sams Teach Yourself ASP.NET 2.0 in 24 Hours》。 可以通过 mitchell@4GuysFromRolla.com 联系到他。
特别致谢
本教程系列由许多有用的审阅者审阅。 本教程的主要审阅者是 Yaakov Ellis、Randy Schmidt 和 Liz Shulok。 有兴趣查看即将发布的 MSDN 文章? 如果是这样,请给我写信。mitchell@4GuysFromRolla.com