作者 :斯科特·米切尔
在本教程中,我们将生成一个接口,该接口使用 Repeater 列出系统中的类别,每个类别都提供一个按钮来使用 BulletedList 控件显示其关联的产品。
介绍
在过去的 17 个 DataList 和 Repeater 教程中,我们创建了只读示例和编辑和删除示例。 为了方便在 DataList 中进行编辑和删除操作,我们在 DataList 的 ItemTemplate
上添加了按钮,这些按钮在被单击时,会导致回发并触发与按钮的 CommandName
属性相对应的 DataList 事件。 例如,在具有CommandName
属性值“编辑”的ItemTemplate
上添加一个按钮,会导致 DataList 在EditCommand
回发时触发事件;而带有CommandName
“删除”的按钮则会引发DeleteCommand
事件。
除了“编辑和删除”按钮之外,DataList 和 Repeater 控件还可以包括按钮、LinkButton 或 ImageButtons,单击时,执行一些自定义服务器端逻辑。 在本教程中,我们将生成一个接口,该接口使用 Repeater 列出系统中的类别。 对于每个类别,Repeater 将包含一个按钮,用于使用 BulletedList 控件显示类别的关联产品(请参阅图 1)。
图 1:单击“显示产品链接”显示项目符号列表中的类别产品(单击以查看全尺寸图像)
步骤 1:添加自定义按钮教程网页
在了解如何添加自定义按钮之前,让我们先花点时间在网站项目中创建本教程所需的 ASP.NET 页面。 首先添加名为 <Site.master
母版页相关联:
Default.aspx
CustomButtons.aspx
图 2:为自定义 Buttons-Related 教程添加 ASP.NET 页
与其他文件夹中一样, Default.aspx
该 CustomButtonsDataListRepeater
文件夹中将列出其部分中的教程。 回想一下, SectionLevelTutorialListing.ascx
用户控件提供了此功能。 通过从解决方案资源管理器将此用户控件拖动到Default.aspx
页面的设计视图来添加该控件。
图 3:将用户控件SectionLevelTutorialListing.ascx
添加到 Default.aspx
(单击以查看全尺寸图像)
最后,将页面添加为文件的条目 Web.sitemap
。 具体而言,在使用 DataList 和 Repeater 进行分页和排序之后,添加以下标记 <siteMapNode>
:
<siteMapNode
url="~/CustomButtonsDataListRepeater/Default.aspx"
title="Adding Custom Buttons to the DataList and Repeater"
description="Samples of DataList and Repeater Reports that Include
Buttons for Performing Server-Side Actions">
<siteMapNode
url="~/CustomButtonsDataListRepeater/CustomButtons.aspx"
title="Using Custom Buttons in the DataList and Repeater's Templates"
description="Examines how to add custom Buttons, LinkButtons,
or ImageButtons within templates." />
</siteMapNode>
更新 Web.sitemap
后,请花点时间通过浏览器查看教程网站。 左侧菜单现在包括用于编辑、插入和删除教程的项目。
图 4:网站地图现在包括自定义按钮教程的条目
步骤 2:添加类别列表
在本教程中,我们需要创建一个 Repeater,它列出所有类别,并包含一个名为“显示产品”的 LinkButton,单击后,会在项目符号列表中显示关联的类别产品。 首先创建一个简单的 Repeater,用于列出系统中的类别。 首先打开 CustomButtons.aspx
文件夹中的页面 CustomButtonsDataListRepeater
。 将 Repeater 从工具箱拖到设计器上,并将其 ID
属性设置为 Categories
。 接下来,从 Repeater 的智能标记创建新的数据源控件。 具体而言,创建一个名为CategoriesDataSource
的新 ObjectDataSource 控件,该控件从类CategoriesBLL
的方法GetCategories()
中选择其数据。
图 5:将 ObjectDataSource 配置为使用 CategoriesBLL
类 s GetCategories()
方法(单击以查看全尺寸图像)
与 Visual Studio 基于数据源创建默认值 ItemTemplate
的 DataList 控件不同,必须手动定义 Repeater 的模板。 此外,必须以声明方式创建和编辑 Repeater 的模板(也就是说,Repeater 智能标记中没有“编辑模板”选项)。
单击左下角的“源”选项卡,在 <h3>
元素中添加一个 ItemTemplate
来显示类别名称,并在段落标签中显示其说明;还包括一个 SeparatorTemplate
,用于在每个类别之间显示一条水平线(<hr />
)。 此外,请添加一个 LinkButton,并将其 Text
属性设置为“显示产品”。 完成这些步骤后,页面的声明性标记应如下所示:
<asp:Repeater ID="Categories" DataSourceID="CategoriesDataSource"
runat="server">
<ItemTemplate>
<h3><%# Eval("CategoryName") %></h3>
<p>
<%# Eval("Description") %>
[<asp:LinkButton runat="server" ID="ShowProducts">
Show Products</asp:LinkButton>]
</p>
</ItemTemplate>
<SeparatorTemplate><hr /></SeparatorTemplate>
</asp:Repeater>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>
图 6 显示通过浏览器查看的页面。 列出了每个类别名称和说明。 单击“显示产品”按钮会导致回发,但尚未执行任何操作。
图 6:显示每个类别的名称和说明,并带有一个显示产品的链接按钮(单击以查看全尺寸图像)
步骤 3:单击“显示产品”链接按钮时执行 Server-Side 逻辑
每当单击 DataList 或 Repeater 中模板内的 Button、LinkButton 或 ImageButton 时,就会发生回发,并触发 DataList 或 Repeater 的事件 ItemCommand
。 除了ItemCommand
事件之外,如果按钮CommandName
的属性设置为保留字符串之一(删除、编辑、取消、更新或选择),DataList 控件也可能引发另一个更具体的事件,但ItemCommand
事件始终会触发。
在 DataList 或 Repeater 中单击某个按钮时,通常需要传递单击的按钮(在这种情况下,控件中可能存在多个按钮,例如“编辑”和“删除”按钮)和一些附加信息(例如单击按钮的项目的主键值)。 Button、LinkButton 和 ImageButton 提供两个属性,其值将 ItemCommand
传递给事件处理程序:
-
CommandName
通常用于标识模板中的每个按钮的字符串 -
CommandArgument
通常用于保存某些数据字段的值,例如主键值
对于此示例,请将 LinkButton s CommandName
属性设置为 ShowProducts,并使用数据绑定语法CategoryArgument='<%# Eval("CategoryID") %>'
将当前记录的主键值CategoryID
绑定到CommandArgument
属性。 指定这两个属性后,LinkButton 的声明性语法应如下所示:
<asp:LinkButton runat="server" CommandName="ShowProducts"
CommandArgument='<%# Eval("CategoryID") %>' ID="ShowProducts">
Show Products</asp:LinkButton>
单击该按钮时,将发生回发,然后 DataList 或 Repeater 的 ItemCommand
事件触发。 事件处理程序被传递按钮的CommandName
和CommandArgument
值。
为 Repeater s ItemCommand
事件创建事件处理程序,并记下传递到事件处理程序(命名 e
)中的第二个参数。 第二个参数的类型 RepeaterCommandEventArgs
如下,具有以下四个属性:
-
CommandArgument
单击的按钮的CommandArgument
属性的值 -
CommandName
按钮 sCommandName
属性的值 -
CommandSource
对被点击的按钮控件的引用 -
Item
是对包含已单击按钮的RepeaterItem
的引用;绑定到 Repeater 的每个记录都显示为RepeaterItem
由于所选类别 CategoryID
是通过 CommandArgument
属性传入的,因此我们可以获取与事件处理程序中 ItemCommand
所选类别关联的产品集。 然后,这些产品可以绑定到项目符号列表控件(我们尚未添加的ItemTemplate
中)。 然后,剩下的就是添加 BulletedList,在 ItemCommand
事件处理程序中引用它,并将其绑定到所选类别的产品集,我们将在步骤 4 中处理。
注释
DataList 的 ItemCommand
事件处理程序接收到一个类型为 DataListCommandEventArgs
的对象,该对象提供了与 RepeaterCommandEventArgs
类相同的四个属性。
步骤 4:以项目列表形式显示所选类别的产品
所选类别的产品可以使用任意数量的控件显示在 Repeater s ItemTemplate
中。 我们可以添加另一个嵌套的 Repeater、DataList、DropDownList、GridView 等。 但是,由于我们希望将产品显示为项目符号列表,因此我们将使用 BulletedList 控件。 返回到 CustomButtons.aspx
页面的声明性标记,将 BulletedList 控件添加到 ItemTemplate
“显示产品链接按钮”之后。 将 BulletedLists ID
设置为 ProductsInCategory
. BulletedList 显示通过 DataTextField
属性指定的数据字段的值。由于此控件将具有绑定到该字段的产品信息,因此请将 DataTextField
属性设置为 ProductName
。
<asp:BulletedList ID="ProductsInCategory" DataTextField="ProductName"
runat="server"></asp:BulletedList>
在ItemCommand
事件处理程序中,使用e.Item.FindControl("ProductsInCategory")
引用此控件,并将其绑定到与所选类别相关联的所有产品集。
Protected Sub Categories_ItemCommand _
(source As Object, e As RepeaterCommandEventArgs) _
Handles Categories.ItemCommand
If e.CommandName = "ShowProducts" Then
' Determine the CategoryID
Dim categoryID As Integer = Convert.ToInt32(e.CommandArgument)
' Get the associated products from the ProudctsBLL and
' bind them to the BulletedList
Dim products As BulletedList = _
CType(e.Item.FindControl("ProductsInCategory"), BulletedList)
Dim productsAPI As New ProductsBLL()
products.DataSource = productsAPI.GetProductsByCategoryID(categoryID)
products.DataBind()
End If
End Sub
在 ItemCommand
的事件处理程序中执行任何操作之前,最好先检查传入 CommandName
的值。
ItemCommand
由于事件处理程序会在单击任何按钮时触发,因此如果模板中有多个按钮,CommandName
的值可用来确定要执行的操作。 对CommandName
进行检查在这里显得毫无意义,因为我们只有一个按钮,但养成这个习惯是好的。 接下来,从CommandArgument
属性中检索所选类别的CategoryID
。 然后,引用模板中的 BulletedList 控件,并将其绑定到类ProductsBLL
方法的GetProductsByCategoryID(categoryID)
结果。
在之前使用 DataList 中的按钮(如 DataList 中编辑和删除数据的概述)的教程中,我们通过 DataKeys
集合确定了给定项的主键值。 虽然此方法适用于 DataList,但 Repeater 没有 DataKeys
属性。 相反,我们必须使用替代方法来提供主键值,例如,通过按钮的CommandArgument
属性,或者将主键值分配给模板中的隐藏 Label Web 控件,并在ItemCommand
事件处理程序中使用e.Item.FindControl("LabelID")
读取其值。
完成 ItemCommand
事件处理程序后,花点时间在浏览器中测试此页面。 如图 7 所示,单击“显示产品”链接会导致回发,并在 BulletedList 中显示所选类别的产品。 此外,请注意,即使单击其他类别“显示产品”链接,此产品信息也会保留。
注释
如果要修改此报表的行为,以便一次只列出一个类别的产品,只需将 BulletedList 控件的属性 EnableViewState
设置为 False
。
图 7:项目符号列表用于显示所选类别的产品(单击以查看全尺寸图像)
概要
DataList 和 Repeater 控件可以在模板中包含任意数量的按钮、LinkButton 或 ImageButton。 单击后,此类按钮会导致回发并引发 ItemCommand
事件。 若要将自定义服务器端动作与按钮单击事件相关联,请为ItemCommand
事件创建事件处理器。 在此事件处理程序中,首先检查传入 CommandName
值以确定单击了哪个按钮。 可以选择通过按钮属性 CommandArgument
提供其他信息。
快乐编程!
关于作者
斯科特·米切尔,七本 ASP/ASP.NET 书籍的作者和 4GuysFromRolla.com 的创始人,自1998年以来一直在与Microsoft Web 技术合作。 斯科特担任独立顾问、教练和作家。 他的最新书是 《Sams Teach Yourself ASP.NET 2.0 in 24 Hours》。 可以通过 mitchell@4GuysFromRolla.com 联系到他。
特别致谢
本教程系列由许多有用的审阅者审阅。 本教程的主要审阅者是丹尼斯·帕特森。 有兴趣查看即将发布的 MSDN 文章? 如果是这样,请给我写信。mitchell@4GuysFromRolla.com