在 DataList 和 Repeater 控件中定制按钮

本文档是 Visual C# 教程 (切换到 Visual Basic 教程)

在本教程中,我们将创建一个界面,方法是使用 Repeater 控件列出系统中的各种类别,每一个类别都提供有一个按钮,用 BulletedList 控件显示与该类别相关的产品。

« 前一篇教程  |  下一篇教程 »

简介

在前面十七个DataList 控件和 Repeater 控件教程中,我们创建了一些只读示例和一些编辑和删除示例。要在 DataList 控件中方便地进行编辑和删除,我们为 DataList 控件的 ItemTemplate 模板添加一些按钮,单击这些按钮时,产生回传并响应按钮的 CommandName 属性引起 DataList 事件。例如,为 ItemTemplate 模板添加一个 CommandName 属性值为“ Edit ” 的按钮,在回传时会激发 DataList 控件的 EditCommand 事件;而对于 CommandName 属性值为 “ Delete ” 的按钮来说则会触发 DeleteCommand 事件。

除了 Edit 按钮和 Delete 按钮外,DataList 控件和 Repeater 控件还可以包含 Button 、LinkButton 、ImageButton ,单击这些按钮将执行一些自定义的服务器端程序。本教程中,我们将创建一个界面,该界面使用 Repeater 控件列出了系统中的各种类别,对于每一种类别,Repeater 控件都将会为其提供一个按钮,用 BulletedList 控件显示与类别相关的产品(请参见图 1 )。

图1 :单击 “Show Products ” 链接以项目符号列表显示该类别的产品

步骤1 :添加定制按钮教程网页

准备添加定制按钮之前,先花点时间在网站项目中创建一些 ASP.NET 页面,我们在教程中将会用到它们。首先添加一个新文件夹,命名为 CustomButtonsDataListRepeater 。接下来,将以下 ASP.NET 页面添加到该文件夹,确保每个页面与 Site.master 母版页相关联:

  • Default.aspx
  • CustomButtons.aspx

图2 :为与定制按钮相关的教程添加 ASP.NET 页面

与在其它文件夹中一样,CustomButtonsDataListRepeater 文件夹中的 Default.aspx 也会列出一些教程。回想一下,SectionLevelTutorialListing.ascx 用户控件提供本功能。将 User Contro 控件从 Solution Explorer 中拖拉到 Default.aspx 页面的设计视图中,向 Default.aspx 页面添加 User Control 控件。

图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 控件,该控件列出所有的类别并带有 “Show Products” 链接按钮,单击此按钮后,以项目符号列表显示相关类别的产品。首先,创建一个简单的 Repeater 控件,列出系统中的各种类别。操作是先打开 CustomButtonsDataListRepeater 文件夹中的 CustomButtons.aspx 页面,从工具箱中拖拉一个 Repeater 控件放到设计器中,并将其 ID 属性设置为 Categories 。接下来,从 Repeater 控件的智能标记创建一个新的数据源控件。具体来说,创建一个新的 命名为 CategoriesDataSource 的 ObjectDataSource 控件,该控件可以从 CategoriesBLL 类的 GetCategories() 方法中选择其数据。

图5 :配置 ObjectDataSource 以使用 CategoriesBLL 类的 GetCategories() 方法

对于DataList 控件,Visual Studio 会根据数据源创建一个默认的 ItemTemplate 模板,而Repeater 控件与 DataList 控件不同,其模板必须手动定义。另外, Repeater 控件的模板必须通过声明来创建和编辑(即,在 Repeater 控件的智能标记中没有 " Edit Templates" 选项)。

单击左下角的 Source 选项卡添加一个ItemTemplate 模板,在 <h3> 元素中显示类别名称,段落标签用于类别描述;再添加一个 SeparatorTemplate 模板,在类别之间显示水平规则(<hr />) 。还要添加一个 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 显示了通过浏览器查看时的页面,其中列出了每个类别的名称和描述。单击 “Show Products” 后,会产生回传但还不会执行任何操作。

图6 :显示每个类别的名称和描述,以及 “Show Products ” 链接按钮

步骤3 :单击"Show Products" 链接按钮时执行服务器端程序

不管什么时候单击 DataList 或 Repeater 控件内模板中的 Button 、LinkButton 、ImageButton ,都会产生回传操作和触发DataList 或 Repeater 控件的 ItemCommand 事件。除了 ItemCommand 事件,如果按钮的 CommandName 属性设置为某个保留字符串( “Delete” 、 “Edit” 、 “Cancel” 、 “Update” 或 “Select” ),DataList 还会引起一些其它的非常特殊的事件,不过 ItemCommand 事件总是会被触发。

单击 DataList 或 Repeater 控件内的按钮时,经常需要分辨哪个按钮被单击(控件内同时存在 多个按钮的情况,例如既有 Edit 按钮又有 Delete 按钮),可能还需要传递一些 其它信息(例如被单击按钮的条目的主键值)。 Button 、 LinkButton 和 ImageButton 提供了两个属性,其属性值传递到 ItemCommand Event Handler中:

  • CommandName – 一个字符串,主要用来辨别模板中的每一个按钮。
  • CommandArgument – 通常用于保存某些数据字段的值,例如主键值。

在本示例中,将 LinkButton 的 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 属性值传递给 Event Handler 。

为Repeater 控件的 ItemCommand 事件创建一个 Event Handler ,请注意传递给 Event Handler 的第二个参数(命名为 e )。第二个参数是 RepeaterCommandEventArgs 类型,拥有下列四个属性:

  • CommandArgument – 被单击按钮的 CommandArgument 属性值
  • CommandName – 按钮的 CommandName 属性值
  • CommandSource – 被单击按钮控件的引用
  • Item – RepeaterItem的引用,包含被单击按钮;绑定到 Repeater 控件的每一条记录都作为一个 Repeater Item

因为通过CommandArgument 属性传递所选定类别的 CategoryID ,我们可以获取与 ItemCommand Event Handler 中所选定类别相关的产品集。随后,将这些产品绑定到 ItemTemplate 模板(我们另外添加)中的 BulletedList 控件上。最后要做的就是添加 BulletedList 控件,并在 ItemCommand Event Handler中引用它,然后将其绑定到所选定类别的产品集上,这些操作我们将在步骤 4 中完成。

注意:DataList 控件的 ItemCommand Event Handler 传入一个 DataListCommandEventArgs 类的对象,该对象提供与RepeaterCommandEventArgs 类相同的四个属性。

步骤4 : 以项目符号列表显示已选定类别的产品

可使用任意数量的控件在 Repeater 控件的 ItemTemplate 内显示已选定类别的产品。我们可以另外添加嵌套的Repeater 控件、DataList 控件、DropDownList 控件、和 GridView 控件等等。因为我们想以照项目符号列表的方式显示产品,所以我们选择使用了 BulletedList 控件。返回到 CustomButtons.aspx 页面的声明式标记处,在 " Show Products " 链接按钮的后面为 ItemTemplate 模板添加一个 BulletedList 控件。将 BulletedLists 的 ID 设置为 ProductsInCategory 。 BulletedList 控件显示通过 DataTextField 属性所指定的数据字段值;因为该控件会将产品信息绑定到自己上,所以要将 DataTextField 属性赋值为 ProductName 。

<asp:BulletedList ID="ProductsInCategory" DataTextField="ProductName"
    runat="server"></asp:BulletedList>

在 ItemCommand Event Handler 中,使用 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  Event Handler 中执行任何操作之前,首先检查传入的 CommandName 值是非常稳妥的做法。因为每当有按钮被单击后,都会触发 ItemCommand Event Handler,所以如果在模板中有多个按钮,可以使用 CommandName 值来辨别应采取的操作。本示例这里检查 CommandName 毫无意义,因为我们只有一个按钮,不过这是一个需要养成的好习惯。接下来,从 CommandArgument 属性中返回已选定类别的 CategoryID 。随后引用模板中的 BulletedList 控件,将该控件绑定到 ProductsBLL 类的 GetProductsByCategoryID(categoryID) 方法的结果上。

在前面那些在DataList 控件中使用按钮的教程中(例如在DataList中进行数据编辑与删除操作概述),我们通过 DataKeys 集确定了指定条目的主键值。虽然这种方法在DataList 控件中非常有效,但是由于 Repeater 控件没有DataKeys 属性,我们必须使用一种替代的方法来提供这个主键值,例如通过按钮的 CommandArgumen 属性或者通过把主键值分配给模板中的隐藏Web 标签控件,然后在 ItemCommand Event Handler 中用 e.Item.FindControl("LabelID") 方法将该值读回。

完成 ItemCommand Event Handler 后,花点时间在浏览器中测试一下这个页面。如图7 所示,单击 "Show Products" 会引起回传,并在 BulletedList 中显示所选定类别的产品。另外需要注意的是,即使单击了其它类别的“ Show Products ”链接,产品信息保持不变。

注意:如果您想修改本报表的行为,例如每次只列出一种类别的产品,只需简单的将 BulletedList 控件的 EnableViewState 属性设置为 False 即可。

图7 :使用 BulletedList 控件显示已选定类别的产品

小结

DataList 和Repeater 控件可以在其模板中包含任何数量的 Button 、LinkButton 或 ImageButton 。单击这些按钮时,会引起回传并触发 ItemCommand 事件。要将用户自定义的服务器端操作和被单击的按钮关联起来,需要为 ItemCommand 事件创建一个 Event Handler。在该 Event Handler中首先检查输入参数CommandName 的值,以确定哪个按钮被单击。另外还可以选择通过按钮的 CommandArgument 属性提供其它的信息。

快乐编程!

 

 

下一篇教程