DataList 和 Repeater 中的自定义按钮 (C#)
在本教程中,我们将生成一个界面,该接口使用中继器列出系统中的类别,每个类别都提供一个按钮,用于使用 BulletedList 控件显示其关联产品。
简介
在过去的 17 个 DataList 和 Repeater 教程中,我们创建了只读示例以及编辑和删除示例。 为了方便 DataList 中的编辑和删除功能,我们向 DataList ItemTemplate
添加了按钮,单击这些按钮时会导致回发并引发对应于按钮属性的 CommandName
DataList 事件。 例如,向 属性值为 Edit 的 添加按钮ItemTemplate
会导致 DataList 在EditCommand
回发时触发;带有 Delete 的CommandName
按钮将引发 DeleteCommand
。CommandName
除了“编辑”和“删除”按钮外,DataList 和 Repeater 控件还可以包括 Buttons、LinkButton 或 ImageButtons,单击这些按钮时会执行一些自定义服务器端逻辑。 在本教程中,我们将生成一个接口,该接口使用中继器列出系统中的类别。 对于每个类别,中继器将包含一个按钮,用于使用 BulletedList 控件显示类别的关联产品 (请参阅图 1) 。
图 1:单击“显示产品”链接显示项目符号列表中的类别产品 (单击以查看全尺寸图像)
步骤 1:添加自定义按钮教程网页
在了解如何添加自定义按钮之前,让我们先花点时间在网站项目中创建本教程所需的 ASP.NET 页面。 首先添加名为 CustomButtonsDataListRepeater
的新文件夹。 接下来,将以下两个 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:添加类别列表
对于本教程,我们需要创建一个中继器,该中继器列出所有类别以及“显示产品链接”按钮,单击该中继器时,会在项目符号列表中显示关联的类别产品。 首先,让我们创建一个简单的中继器,用于列出系统中的类别。 首先打开 CustomButtons.aspx
文件夹中的页面 CustomButtonsDataListRepeater
。 将中继器从工具箱拖到Designer,并将其ID
属性设置为 Categories
。 接下来,从 Repeater 的智能标记创建新的数据源控件。 具体而言,请创建一个名为 CategoriesDataSource
的新 ObjectDataSource 控件,该控件从 CategoriesBLL
类 s GetCategories()
方法中选择其数据。
图 5:将 ObjectDataSource 配置为使用 CategoriesBLL
类 s GetCategories()
方法 (单击以查看全尺寸图像)
与 Visual Studio 基于数据源创建默认值 ItemTemplate
的 DataList 控件不同,中继器模板必须手动定义。 此外,必须以声明方式创建和编辑 Repeater 的模板, (也就是说,Repeater 的智能标记) 中没有“编辑模板”选项。
单击左下角的“源”选项卡,添加一个 ItemTemplate
,该选项卡在元素中 <h3>
显示类别名称,并在段落标记中显示其说明;包括一个 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:显示每个类别的名称和说明,以及显示产品 LinkButton (单击以查看全尺寸图像)
步骤 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 事件 ItemCommand
创建事件处理程序,并记下传递到事件处理程序的第二个参数 (名为 e
) 。 第二个参数的类型 RepeaterCommandEventArgs
为 ,具有以下四个属性:
CommandArgument
单击的按钮属性CommandArgument
的值CommandName
按钮属性CommandName
的值CommandSource
对单击的按钮控件的引用Item
对RepeaterItem
包含已单击按钮的 的引用;绑定到中继器的每个记录都显示为RepeaterItem
由于所选类别是通过 CategoryID
CommandArgument
属性传入的,因此我们可以在事件处理程序中 ItemCommand
获取与所选类别关联的产品集。 然后,这些产品可以绑定到我们尚未添加) (中的 ItemTemplate
BulletedList 控件。 然后,剩下的就是添加 BulletedList,在事件处理程序中 ItemCommand
引用它,并将所选类别的产品集绑定到其中,我们将在步骤 4 中处理。
注意
向 DataList 的 ItemCommand
事件处理程序传递类型为 DataListCommandEventArgs
的对象,该对象提供与 类相同的四个 RepeaterCommandEventArgs
属性。
步骤 4:在项目符号列表中显示所选类别的产品
可以使用任意数量的控件在 Repeater 中 ItemTemplate
显示所选类别的产品。 我们可以添加另一个嵌套中继器、DataList、DropDownList、GridView 等。 但是,由于我们希望将产品显示为项目符号列表,因此我们将使用 BulletedList 控件。 CustomButtons.aspx
返回到页面声明性标记,将 BulletedList 控件添加到ItemTemplate
显示产品 LinkButton 后的 。 将 BulletedLists ID
设置为 ProductsInCategory
。 BulletedList 显示通过 DataTextField
属性指定的数据字段的值;由于此控件将具有绑定到它的产品信息,因此请将 属性 DataTextField
设置为 ProductName
。
<asp:BulletedList ID="ProductsInCategory" DataTextField="ProductName"
runat="server"></asp:BulletedList>
在事件处理程序中 ItemCommand
,使用 e.Item.FindControl("ProductsInCategory")
引用此控件,并将其绑定到与所选类别关联的产品集。
protected void Categories_ItemCommand(object source, RepeaterCommandEventArgs e)
{
if (e.CommandName == "ShowProducts")
{
// Determine the CategoryID
int categoryID = Convert.ToInt32(e.CommandArgument);
// Get the associated products from the ProudctsBLL and bind
// them to the BulletedList
BulletedList products =
(BulletedList)e.Item.FindControl("ProductsInCategory");
ProductsBLL productsAPI = new ProductsBLL();
products.DataSource =
productsAPI.GetProductsByCategoryID(categoryID);
products.DataBind());
}
}
在事件处理程序中ItemCommand
执行任何操作之前,最好先检查传入 CommandName
的值。 由于事件处理程序会在 ItemCommand
单击 任何 按钮时触发,因此如果模板中有多个按钮, CommandName
请使用 值来识别要执行的操作。 CommandName
检查这里是没有意义的,因为我们只有一个按钮,但它是一个很好的习惯形成。 接下来, CategoryID
从 属性检索所选类别的 CommandArgument
。 然后,模板中的 BulletedList 控件将被引用并绑定到 类方法GetProductsByCategoryID(categoryID)
的结果ProductsBLL
。
在之前使用 DataList 中的按钮的教程(例如 DataList 中编辑和删除数据的概述)中,我们通过集合确定了给定项 DataKeys
的主键值。 虽然此方法适用于 DataList,但中继器没有 DataKeys
属性。 相反,我们必须使用替代方法来提供主键值,例如通过按钮的 CommandArgument
属性,或者通过将主键值分配给模板中的隐藏标签 Web 控件,并使用 e.Item.FindControl("LabelID")
在事件处理程序中ItemCommand
读回其值。
完成 ItemCommand
事件处理程序后,请花点时间在浏览器中测试此页面。 如图 7 所示,单击“显示产品”链接会导致回发,并在 BulletedList 中显示所选类别的产品。 此外,请注意,即使单击其他类别“显示产品”链接,此产品信息也会保留。
注意
如果要修改此报表的行为,以便一次仅列出一个类别的产品,只需将 BulletedList 控件的 EnableViewState
属性设置为 False
。
图 7:BulletedList 用于显示所选类别的产品 (单击以查看全尺寸图像)
总结
DataList 和 Repeater 控件可以在其模板中包含任意数量的 Button、LinkButton 或 ImageButton。 单击此类按钮时,会导致回发并引发 ItemCommand
事件。 若要将自定义服务器端操作与单击的按钮相关联,请为 事件 ItemCommand
创建事件处理程序。 在此事件处理程序中,首先检查传入CommandName
值以确定单击的按钮。 可以选择性地通过按钮属性 CommandArgument
提供其他信息。
编程愉快!
关于作者
Scott Mitchell 是七本 ASP/ASP.NET 书籍的作者, 4GuysFromRolla.com 的创始人,自 1998 年以来一直从事 Microsoft Web 技术工作。 Scott 担任独立顾问、培训师和作家。 他的最新书是 山姆斯在24小时内 ASP.NET 2.0自学。 可以在 上联系 mitchell@4GuysFromRolla.com他, 也可以通过他的博客联系到他,该博客可在 http://ScottOnWriting.NET中找到。
特别感谢
本教程系列由许多有用的审阅者查看。 本教程的首席审阅者是 Dennis Patterson。 有兴趣查看我即将发布的 MSDN 文章? 如果是,请在 处放置一行 mitchell@4GuysFromRolla.com。