Repeater里的每个Category都是可点的,而且在点了之后,CategoryProducts DataList会显示那些相关的product。我们可以将每个category设为hyperlink,链到本页(CategoriesAndProducts.aspx),通过querystring为CategoryID赋值。这种方法的好处是,特定category的product可以通为搜索建立索引和书签。
我们也可以将每个category设为LinkButton,在本章我们使用这个方法。LinkButton看起来象一个hyperlink,但是点击后会产生一个postback。DataList的ObjectDataSource会刷新以显示选中category相关联的product。在本章使用hyperlink更合理。然而在别的情况下可以使用LinkButton会好一点。虽然是这样,我们在这里也使用LinkButton。我们将会看到,使用LinkButton会有一些使用hyperlink时碰不到的挑战。因此我们可以学习更好学习它,以便以后使用。
注意:如果你使用HyperLink或<a>来代替LinkButton来重复练习一次本章的内容,是最好不过了。
下面的标记语言是Repeater和ObjectDataSource的,注意Repeater的template将每个item表示为LinkButton。
<asp:Repeater runat="server" DataSourceID="CategoriesDataSource"> <HeaderTemplate> <ul> </HeaderTemplate> <ItemTemplate> <li><asp:LinkButton runat="server" /></li> </ItemTemplate> <FooterTemplate> </ul> </FooterTemplate> </asp:Repeater> <asp:ObjectDataSource runat="server" OldValuesParameterFormatString="original_{0}" SelectMethod="GetCategories" TypeName="CategoriesBLL"> </asp:ObjectDataSource>
注意:在本章Repeater的view state必须开启(Repeater的声明语法里的EnableViewState="False")。在第三步我们将为ItemCommand事件创建一个event handler,在它里面我们要更新DataList的ObjectDataSource的SeleceParameters集合。如果view state 被禁用的话Repeater的ItemCommand不会被激发。想了解具体的原因和更多的信息请参考 A Stumper of an ASP.NET Question 和its solution 。
ID为ViewCategory的LinkButton还没有设置Text属性。如果我们只需要显示category名字,我们可以通过绑定语法象下面这样来直接设置:
<asp:LinkButton runat="server" Text='<%# Eval("CategoryName") %>' />
然而在这里我们需要显示的是category的name和proudct的总数。见下面的代码:
protected void Categories_ItemDataBound(object sender, RepeaterItemEventArgs e) { // Make sure we're working with a data item... if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem) { // Reference the CategoriesRow instance bound to this RepeaterItem Northwind.CategoriesRow category = (Northwind.CategoriesRow) ((System.Data.DataRowView) e.Item.DataItem).Row; // Determine how many products are in this category NorthwindTableAdapters.ProductsTableAdapter productsAPI = new NorthwindTableAdapters.ProductsTableAdapter(); int productCount = productsAPI.GetProductsByCategoryID(category.CategoryID).Count; // Reference the ViewCategory LinkButton and set its Text property LinkButton ViewCategory = (LinkButton)e.Item.FindControl("ViewCategory"); ViewCategory.Text = string.Format("{0} ({1:N0})", category.CategoryName, productCount); } }
我们首先要确保我们处理的是data item(ItemType为Item或AlternatingItem)然后引用刚刚绑定到当前RepeaterItem的CategoriesRow。然后调用GetCategoriesByProductID(categoryID)方法,通过Count属性获取返回的记录条数。最后将ItemTemplate里的ViewCategory LinkButton的Text属性设为"CategoryName(NumberOfProductsInCategory)"。
注意:我们也可以在ASP.NET页的code-behind里写一个格式化功能,接收CategoryName和CategoryID的值,返回CategoryName和product总数的连接字符串。然后将结果直接赋给LinkButton的Text属性,而不需要处理itemDataBound事件。更多的格式化功能信息参考在GridView控件中使用TemplateField 和格式化DataList和Repeater的数据。添加完event handler后,在浏览器里看看页面。见图4。
图 4: 显示每个 Category的 Name 和 Products总数
更新CategoriesDataTable和CategoriesTableAdpter来包含每个Category的Product总数除了在每个category绑定到Repeater时获取product总数外,我们还可以修改DAL里CategoriesDataTable和CategoriesTableAdapter来包含这个信息.我们在CategoriesDataTable里加一列.打开App_Code/DAL/Northwind.xsd,右键点DataTable,选择Add/Column.见图5.