手机版

在ASP.NET 2.0中操作数据:数据控件的嵌套

时间:2021-10-31 来源:互联网 编辑:宝哥软件园 浏览:

介绍

除了静态HTML和数据绑定语法,模板还可以包含Web控件和用户控件。这些控件的属性可以通过服务器端的声明语法、数据绑定语法或事件处理编程来设置。

通过将控件嵌入模板,您可以自定义界面并改善用户体验。例如,在GridView控件中使用TemplateField时,我们学习了如何将Calendar控件添加到GridView的TemplateField中,以指示员工的雇佣日期。我们学习了如何通过在编辑和添加界面中添加验证控件、文本框、下拉列表和其他网络控件来自定义编辑和插入界面。

模板还可以包含其他数据控件。也就是说,我们可以让DataList包含其他的数据列表(或者Repeater、GridView、DetailsView等)。)在模板中。这项工作的挑战在于将数据绑定到内部的数据控件。有几种不同的方法可以实现这一点,包括使用ObjectDataSource的声明语言来指导编程。

在本章中,我们将探讨如何使用嵌套中继器。外层的中继器将每个类别显示为一个项目,包括每个类别的名称和描述。每个类别项目中的中继器显示该类别下的每个产品(见图1)。我们将学习如何通过声明和编程在内层创建中继器。

//files.jb51.net/file_images/article/201605/2016050911243563.png

图1:类别与其产品一起列出。

第一步:创建一个类别列表。

当创建使用嵌套数据控件的页面时,我发现从最外层控件的设计、创建和测试开始非常有帮助,此时,没有必要处理内层的嵌套控件。因此,我们首先在页面中添加一个Repeater来列出类别的名称和描述。

在数据列表重复基础文件夹中打开嵌套控件. aspx页面,添加一个重复控件,并将标识设置为类别列表。通过其智能标记,选择并创建一个名为CategoriesDataSource的新对象数据源。

//files.jb51.net/file_images/article/201605/2016050911243564.png

图2:创建一个名为类别数据源的对象数据源。

使用CategoriesBLL类的GetCategories方法来配置o。

//files.jb51.net/file_images/article/201605/2016050911243565.png

图3:使用CategoriesBLL类的GetCategories方法配置ObjectDataSource。

我们需要切换到源代码视图,手动输入声明代码来指定Repeater的模板内容。添加一个带有h4名称和P描述的项目模板。使用hr来分隔类别。这样做之后,页面代码中Repeater和ObjectDataSource的声明语言应该类似于下面的:

asp: repeater ID=' CategoryList ' DataSourceID=' categoriesdata source ' EnableViewState=' False ' runat=' server ' item template H4 % # Eval(' CategoryName ')%/H4 p % # Eval(' Description ')%/p/item template separate template HR//separate template/asp3360 repeaterasp 3360 objectdata source ID=' categoriesdata source ' runat=' server ' oldvaluesparametertformatstring=' origin _ { 0

//files.jb51.net/file_images/article/201605/2016050911243566.png

图4:列出了每个类别的名称和描述,用水平线隔开。

步骤:添加嵌套中继器以显示产品。

我们的下一个任务是在类别列表的项目模板中添加一个中继器,以显示属于每个类别的产品。有许多方法可以访问内层的Repeater数据。我们将讨论两种。现在我们在CategoryList Repeater的ItemTemplate中创建产品Repeater。每个产品将包含名称和价格。我们将向类别列表的项目模板添加以下标签。

asp3360 Repeater ID=' productbycategorylist ' EnableViewState=' False ' runat=' server ' header template ul/header template item template listrong % # Eval(' Product name ')%/strong(% # Eval('单价',' {0:c}')%)/Li/item template页脚模板/ul/页脚模板/ASP 3360 repeater第三步3360是将每个类别下的产品绑定到ProductsByCategoryList Repeater。

如果现在你浏览这个页,你会看到象图四一样的页面,因为我们还没有在中继器里绑定任何数据。有几种方法可以将合适的产品记录绑定到中继器里,其中一些会比较有效。现在主要的任务是为指定种类取到合适的产品。可以通过在模板列里语法声明对象数据源或者直接在后台代码编程来将数据绑定到内层的复读机。

通过对象数据源和项绑定事件来获取数据

这里我们还是用对象数据源来实现产品BLL .类的GetProductsByCategoryID(类别)方法可以返回特定分类编号的制品信息。因此,我们将在类别列表中继器的模板列里新建一个ObjectDataSource,并用这个方法配置它。不幸的中继器不允许通过设计视图来修改模板,因此我们需要手动添加将声明语法。见下面的代码:

H4 % # Eval(' CategoryName ')%/h4p % # Eval(' Description ')%/pasp :中继器ID=' productbycategorylist ' EnableViewState=' False '数据源ID=' productbycategorydata source ' runat=' server '标题模板ul/标题模板项模板listrong % # Eval('产品名称')%/strong-作为% # Eval(' quantityperunit ')%位于% # Eval(' UnitPrice ',' {0当使用对象数据源方法时我们需要设置产品分类列表中继器的数据源为对象数据源(产品分类数据源).注意对象数据源有一个ASP :参数来指定传给getproductbycategoryid(categoryID)的类别1 .但是我们怎么来指定这个值呢?我们可以设置默认值属性为ASP :参数,见下面的代码:

asp:参数名称='CategoryID '类型='Int32 '默认值='%# Eval('CategoryID')' /不幸的,数据绑定语法只能用在有数据绑定事件的控件里。参数类没有这样的事件,因此这样使用会出错。我们需要为类别列表中继器的项绑定事件创建一个事件处理来设置这个值。每个项目绑定到中继器时激发项绑定事件事件。因此每次外层的中继器激发这个时间时,我们可以将当前的CaegoryID的值传给产品分类数据源对象数据源的分类编号参数。下面的代码是为类别列表中继器的项绑定事件创建一个事件处理器:

受保护的void CategoryList _ ItemDataBound(对象发送方,repeateritemEventargs e){ if(e . item。项目类型==列表项目类型.交替项目。项目类型==列表项目类型.项目){ //引用正在绑定到此重复北风项目的类别当前对象。类别流类别=(北风。类别流()(系统。数据行视图)。划;//引用productbycategorydata源对象数据源object data source product by category data source=(object data source)e . item。查找控件(' productbycategorydata source ');//设置分类编号参数值产品分类数据源.选择参数['CategoryID'].默认值=类别CategoryID .ToString();}} 这个事件处理程序首先保证我们操作的是数据项目而不是页眉、页脚或分隔符项。然后,引用刚刚绑定到当前重复项目的类别当前实例。最后,引用在模板列里的对象数据源并将当前重复项目的分类编号传给分类编号参数。

在这个事件处理程序里,每个重复项目里的产品分类列表中继器都绑定到重复项目的种类里的产品。见图5.

//files.jb51.net/file_images/article/201605/2016050911243567.png

图5: 外层的中继器列出每个类别;内层的中继器列出属于种类的制品

直接编程来获取种类下的制品

除了使用ObjectDataSource获取当前类别下的产品外,还可以在ASP.NET页面的代码隐藏中找到它(或者在App_Code文件夹中或者在单独的类项目中)。创建一个方法,根据传入的类别返回适当的产品集。假设在ASP.NET页面的代码隐藏中有一个名为GetProducintAggrey(Categoryid)的方法。我们可以使用这种方法将当前类别下的产品绑定到内层Repeater。参见以下代码:

asp: repeater runat=' server ' ID=' ProductsByCategoryList ' EnableViewState=' False ' data source=' % # GetProductsInCategory((int)(Eval(' CategoryID '))% './ASP : Repeater的DataSource属性指定其数据由getproducticategoryid(categoryid)通过绑定语法获得。由于Eval('CategryID ')返回对象类型,因此我们将其转换为整数,然后再将其传递给getproductincogerid(CategoryID)。注意这里的Categoryid是通过外层Repeater(CategoryList)的CategoryID(已经绑定到Categorietable)获得的。因此,它不能是空值。因此,我们在绑定前没有检查。

现在我们需要创建一个GetProductionInCategory(Categoryid)方法。这里我们只需使用ProductsBLL类的getproductbycategoryid(Categoryid)。该方法返回的产品数据表正常。我们在NestedControls.aspx页面的代码隐藏中创建了getproductincogory(categoryid)。参见以下代码:

受保护的北风。productdatatable GetProductionInCategory(int categoryID){//创建ProductBLl类的实例ProductBLl ProductAPI=new ProductBLl();//返回类别中的产品返回productAPI。getproductbycategoryid(categoryID);}此方法仅创建一个ProductsBLL实例,然后返回getproductbycategoryid(categoryid)方法的返回值。请注意,此方法必须标记为公共或受保护。如果它被标记为私有,ASP。NET不能在ASP的声明标记中调用。网页。完成上述操作后,在浏览器中浏览页面。该页面看起来应该类似于使用ObjectDataSource和ItemDataBound事件处理程序方法(图5)。

请注意,在ASP.NET页面的代码隐藏中创建的getproducticategoryid(categoryid)方法似乎只是一种形式。毕竟这个方法只调用BLL的方法。为什么不直接在内层Repeater的绑定语法中调用这个方法呢?例如, datasource=' % # productsbll。getproductbycategoryid(ctype(eval)(“categoryid”),虽然这个声明是无效的(因为getproductbycategoryid(categoryid)方法是一个实例方法),但是您可以修改ProductsBLL以包含这样一个静态方法。这种修改可以满足ASP.NET页面的getproductinchategoryid(categoryid)方法的需求,但是用代码隐藏的方式编写可以更灵活的获取数据,我们后面会看到。

获取所有产品信息。

在前两种方法中,我们调用ProductsBLL类的getproductbycategoryid(categoryid)方法来获取当前类别的产品(第一种是通过ObjectDataSource,第二种是通过getproductingcategoryid(categoryid))。每次调用该方法时,BLL都会调用dal,dal通过SQL查询数据库并返回特定的记录。

如果有N个类别,该方法将访问数据库N次-一次返回所有类别,N次返回特定类别下的产品。但是,我们可以访问数据库两次以获取所有需要的数据-一次返回所有类别,一次返回所有产品。一旦我们得到了所有的产品,我们就可以根据CategoryID进行过滤,然后绑定它们。

我们只需要稍微修改一下ASP.NET的代码隐藏页面中的getproductingintegrary(CategoryID)方法就可以实现这个功能。我们首先返回所有产品,然后根据输入的类别进行过滤。

二等兵北风。products datatable all products=null;受保护的北风。productdatatable GetProductsInCategory(int categoryID){//首先,看看我们是否还没有访问所有的产品信息,如果(all products==null){ product bll product API=new product bll();allProducts=productAPI。GetProducts();} //返回所有产品的筛选视图。default view . row filter=' CategoryID=' CategoryID;返回所有产品;}注意allProducts变量。它在第一次调用getproducticategoryid(categoryid)时返回所有产品信息。在确认创建了allProducts对象后,根据categoryid过滤DataTable。这种方法将访问数据库的次数从N 1次减少到2次。这种改进并没有修改页面的声明语言,只是减少了访问数据库的次数。

请注意,可能认为减少数据库访问次数会提高性能是理所当然的。然而,情况未必如此。如果您有大量空类别标识的产品,GetProducts方法返回的一些产品将不会显示。而且,如果只需要显示品类的一部分proudct(分页时就是这种情况),把所有产品都退回也是浪费资源。通常对两种技术进行性能分析,唯一正确的方法是设置程序的公共场景进行压力测试。

摘要

在本章中,我们学习了如何嵌套Web控件。例如,通过在外部Repeater上显示每个类别,在内部Repeater上显示每个类别下的产品,主要任务是获取正确的数据并将其绑定到内部Web控件。有许多方法可以使用。这里讨论的有两种。第一种是在外部控件的ItemTemplate中使用ObjectDataSource绑定到内部控件。第二种是在ASP.NET页面的代码隐藏中使用方法。它由内部控件的DataSource属性绑定。本章使用的控件是Repeater,它也可以嵌套在GridView或DataList中的GridView中。

编程快乐!

作者简介

斯科特米切尔,六本关于ASP/ASP的书的作者。NET,是4GuysFromRolla.com的创始人,自1998年以来一直使用微软的网络技术。Scott是一名独立的技术顾问、培训师和作家,最近完成了一部即将由Sams出版社出版的新作,24小时内精通ASP.NET 2.0。他的联系电子邮件是[emailprotected],也可以通过他的博客http://ScottOnWriting.NET联系到他。

版权声明:在ASP.NET 2.0中操作数据:数据控件的嵌套是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。