在ASP.NET 2.0中操作数据之四十五:DataList和Repeater里的自定义Button
导言
在前面关于datalist 和repeater 的7章教程里,我们分别创建了只读和可以编辑删除的例子。为了让datalist有编辑和删除的功能,我们在itemtemplate里添加了一些button,当点击时,引起postback,并根据button的commandname属性激发相关的事件。例如,添加一个commandname为“edit”的button,在postback时会激发editcommand事件,如果commandname为“delete”则激发deletecommand。
除了编辑和删除button,datalist和repeater还可以包含一些当点击时,执行自定义服务器端逻辑的button,linkbutton和imagebutton。本章我们将创建一个在repeater里列出categories的界面。每个category都包含一个button,当点击时会列出相关product。见图1。
图 1: 点 “show products” 显示目录下所有product
第一步: 添加教程页
首先添加本章需要的页。添加一个名为custombuttonsdatalistrepeater的文件夹。然后添加下面两个页,记得包含site.master母板页。
default.aspx
custombuttons.aspx
图 2: 添加页
和其它文件夹一样,custombuttonsdatalistrepeater文件夹下的default.aspx页会列出本部分的教程。和前面一样添加sectionleveltutoriallisting.ascx用户控件。
图 3: 添加 sectionleveltutoriallisting.ascx用户控件
最后,在web.sitemap里添加这些页的信息。见下面的标记:
<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>
完成后浏览该页。见图4。
图 4: 现在的站点地图包含了本章的页
第二步: 添加 categories列表
我们需要添加一个列出所有categories,每个category都有一个“show products” linkbutton的repeater。点linkbutton时会显示所有category相关的products。我们首先创建一个列出所有categories的repeater。打开custombuttons.aspx页,拖一个repeater进来,将id设为categories。然后从智能标签里创建一个名为categoriesdatasource的objectdatasource,用categoriesbll类的getcategories()方法配置它。
图5: 配置objectdatasource
visual studio会根据数据源为datalist创建一个默认的itemtemplate,而repeater的templates需要手工定义。而且repeater的templates需要直接通过声明代码来创建和修改(也就是说在智能标签上没有“edit templates”选项)
点左下角的源视图,添加一个以<h3>显示category name,以段落description的itemtemplate。并包含一个在每个category之间显示水平线(<hr />)的separatortemplate。同样还要添加一个linkbutton,将text设为“show products”。完成这些后你的页面声明代码应该和下面差不多:
<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是浏览该页的样子。每个category name和description都被列出来。当点“show products” button时会引起postback,但是还不执行任何功能。
图 6: 每个 category'的name 和 description 和 “show products” linkbutton一起列出
第三步:当点“show products” linkbutton 时执行服务器端代码
任何时候,当datalist或repeater的template里的button, linkbutton, imagebutton被点时,会产生postback,并激发datalist或repeater的itemcommand事件。除了itemcommand外,如果button'的commandname 设为(“delete”, “edit”, “cancel”, “update”, “select”)其中一个时,datalist会激发另外一个事件。但是itemcommand是都会激发的。
当datalist或repeater的template里的button被点时,通常我们需要获取哪个button被点了(一个控件里可能有多个button,比如编辑和删除),还可能需要一些其它的信息(比如那些button被点的item(项)的主键)。button, linkbutton, imagebutton提供了两个属性,它们的值可以传给itemcommand event handler:
commandname –表示template里每个button身份的字符串 。
commandargument – 通常用来保存一些值,比如主键。
在这个例子里,将linkbutton的commandname设为“showproducts”,并将当前记录的主键– categoryid –通过绑定语法绑定到commandargument(categoryargument='<%# eval("categoryid") %>')。完成这些后,linkbutton的声明语法看起来应该和下面差不多:
<asp:linkbutton runat="server" commandname="showproducts" commandargument='<%# eval("categoryid") %>' id="showproducts"> show products</asp:linkbutton>
当button被点时,产生postback并激发datalist或repeater的itemcommand事件。button的commandname和commandargument值被传到event handler里。
为itemcommand事件创建一个event handler,注意event handler的第二个参数(名字为e)。这个参数的类型为repeatercommandeventargs,它有以下4个属性:
commandargument – 被点的 button'的commandargument property 的值
commandname – button'的commandname property 的值
commandsource – 被点 button 的引用
item – 包含被点button 的 repeateritem的引用; 每条绑定到repeater的记录被表明为一个 repeateritem
由于选择的category的categoryid通过commandargument传入,我们可以在itemcommand event handler里获取与之相关的products。这些products在itemtemplate(我们已经添加过了)里绑定到一个bulletedlist。剩下的事就是添加bulletedlist,在itemcommand event handler里引用它,然后将选择的category的products绑定到bulletedlist,我们将在第四步完成这个。
注意:datalist的itemcommand event handler传入了一个datalistcommandeventargs类型的对象,它提供和repeatercommandeventargs 一样的4个属性。
第四步: 显示选择的category的 products
在itemtemplate里显示products可以使用很多控件,我们可以添加一个嵌套的repeater,datalist,dropdownlist,gridview等。在这里我们使用bulletedlist。回到custombuttons.aspx page页的声明代码,在“show products” linkbutton后添加一个bulletedlist。将id设为productsincategory。bulletedlist显示那些通过datatextfield属性指定的字段值。由于将有product信息绑定到这个属性,我们将datatextfield设为productname。
<asp:bulletedlist id="productsincategory" datatextfield="productname" runat="server"></asp:bulletedlist>
在itemcommand event handler里通过e.item.findcontrol("productsincategory")引用这个控件,并与products绑定。
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 event handler里执行任何操作前,需要先检查传入的commandname。由于itemcommand event handler在任何button被点时都会执行,如果在template里有多个button时需要通过commandname的值来辨别需要采取什么操作。由于我们这里只有一个button,因此在这里检查commandname是没意义的,但是这是一个好习惯。然后,选择的category的categoryid通过commandargument获取。然后引用template里的bulletedlist并绑定productsbll类的getproductsbycategoryid(categoryid)方法的结果。
在前面datalist里使用button的教程里,比如在datalist里编辑和删除数据概述,我们通过datakeys集合来获取给定item的主键。这个方法在datalist里很好用,但是repeater没有datakeys属性。因此我们需要换一种方法来提供主键的值,比如通过button的 commandargument,或者在template使用一个隐藏的label,然后通过e.item.findcontrol("labelid")在itemcommand event handler里读出它的值。
完成itemcommand event handler后,浏览该页。见图7。点“show products” link会引起postback,并显示相关的products。而且,注意当点其它“show products” links时前面的product信息会保留。
注意:如果你需要修改这个报表的行为,比如一次只列出一个category的products,仅仅只需要将bulletedlist的enableviewstate属性设为false。
图 7: 用 bulletedlist 显示选择category关联的 products.
总结
datalist和repeater可以在templates里包含很多buttons, linkbuttons, imagebuttons。这些button被点时会引起postback,并激发itemcommand事件。为itemcommand event.创建一个event handler可以将服务器端代码和点击button关联起来。在这个event handler里首先检查传入的commandname的值来判断是哪个button被点了。其它另外的信息可以通过commandargument属性来提供。
祝编程快乐!
作者简介
本系列教程作者 scott mitchell,著有六本asp/asp.net方面的书,是4guysfromrolla.com的创始人,自1998年以来一直应用 微软web技术。大家可以点击查看全部教程《[翻译]scott mitchell 的asp.net 2.0数据教程》,希望对大家的学习asp.net有所帮助。