电信主站 网通分站
购买流程 付款方式 常见问题 在线提问 续租服务 购物车
用户名: 密 码: 忘记密码?
首 页
域名注册
虚拟主机
双线主机
服务器租用
VPS主机
企业邮局
代理专区
客服中心
虚拟主机行业资讯 虚拟主机评测对比 互联网最新动态 技术学院 站长资讯 在线教程 网站运营
搜索优化 服务器 网络编程 图形图象 站长之家 网页制作 操作系统
冲浪宝典 软件教学 视频通信 办公软件 邮件系统 网络安全 认证考试
您当前位置:西部数码->资讯中心-> 在线教程-> .NET
Mastering ASP.Net DataBinding-ASP教程,ASP应用
作者:网友供稿 点击:42
  西部数码-全国虚拟主机10强!20余项虚拟主机管理功能,全国领先!第6代双线路虚拟主机,南北访问畅通无阻!虚拟主机可在线rar解压,自动数据恢复设置虚拟目录等.虚拟主机免费赠送访问统计,企业邮局.Cn域名注册10元/年,自助建站480元起,免费试用7天,满意再付款!P4主机租用799元/月.月付免压金!
文章页数:[1] 
begin:

mastering asp.net databinding
karl seguin ?karlseguin@hotmail.com


table of contents
introduction
the sample program
understanding dataitem
formatting
inline
onitemdatabound
onitemcreated
nested binding
inline
onitemdatabound
handling events
download

this article is available at code project. check it out to make comments, discuss or rate the article

id like to thank jean-claude manoli for developing his c# code format, which i used in writing this tutorial.
introduction
questions regarding databinding, in one form or another, are probably the most asked in the aspnet newsgroups. its clear everyone loves the idea of databinding but that more advanced functionality, such as event handling, conditional formatting and fine-tuning, arent straightforward. the goal of this tutorial is shed light on some of the more common and frequently asked questions about the capabilities of databinding.
the sample program
throughout this tutorial well use two separate data sources. the first will be your every-day dataset, the other will be a strongly-typed custom collection containing strongly-typed objects.

our dataset will contain two tables, customers and orders:
customer structure order structure
name type description name type description
customerid1 int32 unique customer identifier orderid int32 unique order identifier
name string name of the customer customerid1 int32 identifier of the custom who placed the order
zip string customers primary zip or portal code ordered datetime date the order was placed on
enabled boolean whether the customer is currently active/enabled amount decimal dollar value of the order

1a datarelation exists between the customer.customerid and order.customerid columns.

our business entities will consist of an owner and a pet class:
owner structure pets structure
name type description name type description
ownerid int32 unique owner identifier petid int32 unique pet identifier
yearofbirth int32 the year the owner was born in name string name of the pet
firstname string owners first name isneutured boolean whether or not the pet is neutured
lastname string owners last name type pettype indicates the type of pet (dog, cat, fish, bird, rodent, other)
pets petcollection collection of pets the owner has

understanding dataitem
youve undoudbtedly made frequent use of the dataitem property, namely when using the databinding syntax to output a value:
1: <%# databinder.eval(container.dataitem, "customerid") %>
its important to understand that dataitem is actually an object, and that when you use the databinder.eval function, it basically needs to figure out what type of object it is and how to get "customerid" from it. thats because your datasource can be different things, such as a dataset or dataview, an arraylist or hashtable, a custom collection and more. binding happens on a row-by-row basis and dataitem actually represents the current row being bound. for a dataset, datatable or dataview dataitem is actually an instance of datarowview (you might think that the dataitem for a dataset or datatable would be an instance of datarow, but when you bind either of these, the defaultview is actually used, therefore dataitem will always be a datarowview). when you are binding to a collection, dataitem is an instance of the item within the collection. we can observe this more clearly with the following code:
1: <%@ import namespace="system.data" %>
2: <%@ import namespace="bindingsample" %>
3: <asp:repeater id="datasetrepeater" runat="server">
4: <itemtemplate>
5: <%# ((datarowview)container.dataitem)["customerid"] %> -
6: <%# ((datarowview)container.dataitem)["name"] %> <br />
7: </itemtemplate>
8: <alternatingitemtemplate>
9: <%# databinder.eval(container.dataitem, "customerid") %> -
10: <%# databinder.eval(container.dataitem, "name") %> <br />
11: </alternatingitemtemplate>
12: </asp:repeater>
13:
14: <br><br>
15:
16: <asp:repeater id="collectionrepeater" runat="server">
17: <itemtemplate>
18: <%# ((owner)container.dataitem).ownerid %> -
19: <%# ((owner)container.dataitem).firstname %> <br />
20: </itemtemplate>
21: <alternatingitemtemplate>
22: <%# databinder.eval(container.dataitem, "ownerid") %> -
23: <%# databinder.eval(container.dataitem, "firstname") %> <br />
24: </alternatingitemtemplate>
25: </asp:repeater>

in the first repeater we are binding to a dataset, the itemtemplate shows how to access values by casting dataitem to a datarowview [5,6], the alternateitemtemplate will output the same information but through databinder.eval [9,10].

in the second repeater we bind to a custom collection, again the itemtemplate shows how to cast dataitem to the right type and access the fields directly [18,19] while the alternateitemtemplate shows how the same is accomplished with databinder.eval [22,23].

in both cases the itemtemplate and alternateitemtemplate will output the exact same information. the only difference is how the information is retrieved. databinder.eval is far less performant, but has the benefit of being ignorant of the underlying structure, making it both quicker to develop and more likely to resist future changes. the goal here isnt to discuss the merits of these approaches, but simply show what dataitem truly is in order to build a proper foundation of understanding.
formatting
inline
while binding its possible to do simple formatting directly in the databinding expression or by calling functions which reside in codebehind.
1: <asp:repeater id="datasetrepeater" runat="server">
2: <itemtemplate>
3: <%# databinder.eval(container.dataitem, "orderid")%> -
4: <%# formatdate(databinder.eval(container.dataitem, "ordered"))%> -
5: <%# formatmoney(databinder.eval(container.dataitem, "amount"))%> <br />
6: </itemtemplate>
7: </asp:repeater>
8:
9: <br ><br >
10:
11: <asp:repeater id="collectionrepeater" runat="server">
12: <itemtemplate>
13: <%# databinder.eval(container.dataitem, "ownerid") %> -
14: <asp:literal id="see" runat="server"
15: visible=<%# (int)databinder.eval(container.dataitem, "pets.count") > 0 %>>
16: see pets
17: </asp:literal>
18: <asp:literal id="nopets" runat="server"
19: visible=<%# (int)databinder.eval(container.dataitem, "pets.count") == 0 %>>
20: no pets
21: </asp:literal>
22: <br />
23: </itemtemplate>
24: </asp:repeater>
the second repeater makes use of directly embedded expressions to toggle the visibility of certain controls [15,19]. the first repeater, which is bound to all orders, makes use of two functions: formatdate [4] and formatmoney [5]. these methods could look something like:
1: protected string formatdate(object date) {
2: if (date == dbnull.value){
3: return "n/a";
4: }
5: try{
6: return ((datetime)date).toshortdatestring();
7: }catch{
8: return "n/a";
9: }
10: }
11: protected string formatmoney(object amount) {
12: if (amount == dbnull.value){
13: return string.format("{0:c}", 0);
14: }
15: return string.format("{0:c}", amount);
16: }


onitemdatabound
while the above method is suitable for quick and simple problems, it lacks in elegance and capacity. indeed, the 2nd example shows a serious lack of grace and dangerously blends presentation logic with ui. avoiding burdening your presentation layer with any code is a practice worth eternal vigilence. to help accomplish this, the repeater, datalist and datagrid all expose a very powerful and useful event: onitemdatabound.

onitemdatabound fired for each row being bound to your datasource (in addition to when other templates are bound (header, footer, pager, ..)), it not only exposes the dataitem being used in binding, but also the complete template. onitemdatabound starts to fire as soon as the databind() method is called on the repeater/datalist/datagrid.

using onitemdatabound lets us exercise fine control over exactly what happens during binding in a clean and robust framework. for example, reworking the 2nd repeater from above, we get:
1: <asp:repeater onitemdatabound="itemdataboundrepeater_itemdatabound" id="itemdataboundrepeater" runat="server">
2: <itemtemplate>
3: <%# databinder.eval(container.dataitem, "ownerid") %> -
4: <asp:literal id="see" runat="server" /> <br />
5: </itemtemplate>
6: </asp:repeater>
notice that our previously code-cluttered itemtemplate is now considerably cleaner - this is because weve pushed the logic to the itemdataboundrepeater_itemdatabound function in codebehind:
1: protected void itemdataboundrepeater_itemdatabound(object source, repeateritemeventargs e) {
2: if (e.item.itemtype == listitemtype.alternatingitem || e.item.itemtype == listitemtype.item){
3: literal lit = (literal)e.item.findcontrol("see");
4: if (lit != null){
5: owner owner = (owner)e.item.dataitem;
6: if (owner.pets.count == 0){
7: lit.text = "no pets";
8: }else{
9: lit.text = "see pets";
10: }
11: }
12: }
13: }
since we are dealing with repeaters, e.item returns a reference to the current repeateritem. if this was a datalist, it would return a reference to a datalistitem, or a datagriditem if it were a datagrid. for the most part however, all three provide the same capabilities. the first thing to do is check the itemtype and make sure we are currently dealing with an alternateitem or an item [2]. next get a reference to our literal [3], this is an extremely powerful capability which allows us to really keep our ui clean. as we saw in a previous section, we can cast dataitem directly to the individual item being bound (in this case owner, but again, if we bound to a dataset, it would be a datarowview) [5]. finally all the pieces are in place to apply our presentation logic [6-10].

an alternative to using e.item.findcontrol() is to refer to the controls by position via e.item.controls[index]. while this may be considerably faster, it really makes the ui inflexible to basic changes (else you face constantly changing the code). additionally, white spaces and newlines are actually controls. so in the above code, youd get:
1: e.item.controls[0] //"\r\n 1 - \r\n "
2: e.item.controls[1] //is the actual "see" literal
which is both an unexpected behaviour and one very hard to cleanly deal with.

when it comes to onitemdatabound, the sky is the limit. here weve only shown a basic example of what can be done and though we will see other, more complex examples, we wont cover every possibility.
onitemcreated
another useful event exposed by these controls is onitemcreated. the key difference between the two is that onitemdatabound only fires when the control is bound - that is when you are posting back and the control is recreated from the viewstate, onitemdatabound doesnt fire. onitemcreated on the other hand fires when a control is bound as well as when the control is recreated from the viewstate. the following example shows this subtle difference:
1: <asp:repeater onitemcreated="repeater_itemcreated" onitemdatabound="repeater_itemdatabound" id="repeater" runat="server">
2: <itemtemplate>
3: <asp:literal enableviewstate="false" id="event" runat="server" /> <br />
4: </itemtemplate>
5: </asp:repeater>
6:
7: <asp:button id="btn" runat="server" text="click me!" />
here we have a repeater with both the onitemcreated and onitemdatabound events hooked [1]. additionaly we have a single literal whos viewstate is disabled (if it was enabled we couldnt see the difference) [3]. and we have a button thatll do nothing but postback [7]. our codebehind looks like:
1: private void page_load(object sender, eventargs e) {
2: if (!page.ispostback){
3: repeater.datasource = customerutility.getallorders();
4: repeater.databind();
5: }
6: }
7: protected void repeater_itemdatabound(object source, repeateritemeventargs e) {
8: if (e.item.itemtype == listitemtype.alternatingitem || e.item.itemtype == listitemtype.item){
9: literal lit = (literal)e.item.findcontrol("event");
10: if (lit != null){
11: lit.text += " - itemdatabound";
12: }
13: }
14: }
15: protected void repeater_itemcreated(object source, repeateritemeventargs e) {
16: if (e.item.itemtype == listitemtype.alternatingitem || e.item.itemtype == listitemtype.item){
17: literal lit = (literal)e.item.findcontrol("event");
18: if (lit != null){
19: lit.text += "itemcreated";
20: }
21: }
22: }
when the page is first loaded, page.ispostback returns false [2] and our repeater is bound to all orders [3,4]. calling databind() causes the itemcreated event to fire for the first row, followed by the itemdatabound event - in our example each will fire, one after the other, 11 times (since there are 11 orders). as we can see, itemcreated and itemdatabound merely take the literal and append the text "itemcreated" and "itemdatabound" respectively. the difference happens when our button is clicked. this causes page_load to fire, but this time page.ispostback evaluates to true, thus skipping the binding [3,4]. only when the page enters its begin prerender stage will the itemcreated event fire (again once for each row), but this time it wont be followed by the itemdatabound.

the really important thing to keep in mind is that when itemcreated fires because of databinding, e.item.dataitem will what you expect - a reference to the individual row being bound. however, when itemcreated is fired from being re-created from the viewstate, e.item.dataitem will be null. if you think about it this makes sense, the entire datasource isnt stored in the viewstate, only the individual controls and their values, as such its impossible to have access to the individual rows of data originally used when binding. of course, this can lead to very buggy code. for example, if we took our previous itemdatabound example and moved it to the itemcreated event:
1: protected void itemcreatedrepeater_itemcreatedobject source, repeateritemeventargs e) {
2: if (e.item.itemtype == listitemtype.alternatingitem || e.item.itemtype == listitemtype.item){
3: literal lit = (literal)e.item.findcontrol("see");
4: if (lit != null){
5: owner owner = (owner)e.item.dataitem;
6: if (owner.pets.count == 0){
7: lit.text = "no pets";
8: }else{
9: lit.text = "see pets";
10: }
11: }
12: }
13: }
when the page first loads, the above code will work fine. but if the page is postedback, e.item.dataitem will be null, resulting in a runtime null reference error.
nested binding
another common requirement is to nest controls within each other. both of our sample data has a 1 to many relationship and are therefore ideal candidates. our customers dataset has a datarelation set up between the customers customerid and the orders customerid:
1: ds.relations.add(new datarelation("customerorders", ds.tables[0].columns["customerid"], ds.tables[1].columns["customerid"]));
and our owners have a pets property which is a collection of all the pets they own.

the two ways that well look at nesting repeaters is via inline binding and using onitemdatabound.
inline
1: <asp:repeater id="datasetcasting" runat="server">
2: <headertemplate>
3: <ul>
4: </headertemplate>
5: <itemtemplate>
6: <li><%# ((datarowview)container.dataitem)["name"]%>
7: <ul>
8: <asp:repeater id="orders" datasource=<%# ((datarowview)container.dataitem).createchildview("customerorders")%> runat="server">
9: <itemtemplate>
10: <li><%# ((datarowview)container.dataitem)["amount"]%></li>
11: </itemtemplate>
12: </asp:repeater>
13: </ul>
14: </li>
15: </itemtemplate>
16: <footertemplate>
17: </ul>
18: </footertemplate>
19: </asp:repeater>
the important part being when we set the datasource of our inner repeater [8]. the createchildview function our datarowview is used, in conjuction with the name of our datarelationship to return a dataview of all child records. alternatively, using the databinder.eval, we could simply use:
1: <asp:repeater id="orders" datasource=<%# databinder.eval(container.dataitem, "cutomerorders")%> runat="server">
again, we use the customerorders datarelation which we created, but let the databinder.eval handle everything else.

nesting with custom collections is even easier. since owners have a property called pets which is a custom collection of all the pets they own, we can simply:
1: <asp:repeater id="collectioncasting" runat="server">
2: <headertemplate>
3: <ul>
4: </headertemplate>
5: <itemtemplate>
6: <li><%# ((owner)container.dataitem).firstname%>
7: <ul>
8: <asp:repeater id="pets" datasource="<%# ((owner)container.dataitem).pets%>" runat="server">
9: <itemtemplate>
10: <li><%# ((pet)container.dataitem).name%></li>
11: </itemtemplate>
12: </asp:repeater>
13: </ul>
14: </li>
15: </itemtemplate>
16: <footertemplate>
17: </ul>
18: </footertemplate>
19: </asp:repeater>
or using databinder.eval:
1: <asp:repeater id="pets" datasource=<%# databinder.eval(container.dataitem, "pets")%> runat="server">
onitemdatabound
if something is doable using inline aspx, its doable via onitemdatabound. deciding which method to use often depends on which you feel is cleaner and more flexible. well only look at one example, since its basically the same as the above code, except the binding logic is moved to codebehind:
1: <asp:repeater onitemdatabound="datasetcasting_itemdatabound" id="datasetcasting" runat="server">
2: <headertemplate>
3: <ul>
4: </headertemplate>
5: <itemtemplate>
6: <li><%# ((datarowview)container.dataitem)["name"]%>
7: <ul>
8: <asp:repeater id="orders" runat="server">
9: <itemtemplate>
10: <li><%# ((datarowview)container.dataitem)["amount"]%></li>
11: </itemtemplate>
12: </asp:repeater>
13: </ul>
14: </li>
15: </itemtemplate>
16: <footertemplate>
17: </ul>
18: </footertemplate>
19: </asp:repeater>
notice that our inner repeater doesnt have a datasource property [8], however our outer repeater does specify an onitemdatabound function [1], lets look at it:
1: protected void datasetcasting_itemdatabound(object s, repeateritemeventargs e) {
2: if (e.item.itemtype == listitemtype.item || e.item.itemtype == listitemtype.alternatingitem){
3: repeater rpt = (repeater)e.item.findcontrol("orders");
4: if (rpt != null){
5: rpt.datasource = ((datarowview)e.item.dataitem).createchildview("customerorders");
6: rpt.databind();
7: }
8: }
9: }
basically the same thing is happening as we saw before, except this is happening out of the ui.
handling events
the last thing to discuss is how to handle events raised by controls inside your repeater/datalist/datagrid. events raised from controls inside your repeater bubble up to the repeater and are exposed via the onitemcommand event. linkbuttons and buttons have a commandargument and commandname property which lets the onitemcommand handler figure out which button was clicked, for example:
1: <asp:repeater onitemcommand="eventrepeater_itemcommand" id="eventrepeater" runat="server">
2: <itemtemplate>
3: <%# databinder.eval(container.dataitem, "name")%> &nbsp;&nbsp;&nbsp;
4: <asp:linkbutton id="delete"
5: runat="server"
6: commandname="delete"
7: commandargument=<%# databinder.eval(container.dataitem, "customerid") %>>
8: delete customer
9: </asp:linkbutton>
10: &nbsp;&nbsp;&nbsp; - &nbsp;&nbsp;&nbsp;
11: <asp:linkbutton id="addorder"
12: runat="server"
13: commandname="add"
14: commandargument=<%# databinder.eval(container.dataitem, "customerid") %>>
15: add order
16: </asp:linkbutton>
17: <br />
18: </itemtemplate>
19: </asp:repeater>
in the above code, two linkbuttons can raise events, either deleting the customer [4-9] or adding an order [11-16]. also note that the itemcommand is hooked up [1]:
1: protected void eventrepeater_itemcommand(object s, repeatercommandeventargs e) {
2: int customerid = convert.toint32(e.commandargument);
3: switch (e.commandname.toupper()){
4: case "delete":
5: customerutility.deletecustomer(customerid);
6: bindeventrepeater(false);
7: break;
8: case "add":
9: //doesnt actually do antyhing right now.
10: break;
11: }
12: }
depending on what the commandname is [3] we know different actions were requested. its important to note that if you change the underlaying datasource (like deleting a row) and want that to be visible to the user, you need to rebind your repeater/datalist/datagrid. also note that if you are caching your data, like i am here, youll need to invalidate the cache so that the new data source (with the delete/added/updated rows) is used.
download
this sample web application simply contains a number of pages which do various things with repeaters. it should provide a playground for trying different things and simply messing around with databinding:
c# application
vb.net application



文章整理:西部数码--专业提供域名注册虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!
相关主题
文章页数:[1] 
Google
热门文章
·经典收藏之 - C++内存管理详解-.NET教程,C#语言
·Master Page 初探-.NET教程,评论及其它
·GDI+编程10个基本技巧-.NET教程,评论及其它
·VB.NET中让Textbox只能输入数字(二)-.NET教程,VB.Net语言
·stl应用小问题-.NET教程,评论及其它
·WIN32中颜色值(COLORREF)与.NET中颜色值(Color)的转换-ASP教程,系统相关
·打造自己的专业图像工具-Visual C++ 2005图像编程系列【三】-.NET教程,C#语言
·.Net中常见问题及解决方法归类-.NET教程,.NET Framework
·Lex和Yacc从入门到精通(3)--一个极其简单的lex和yacc程序-.NET教程,评论及其它
·VB下几个非常有用的函数-.NET教程,VB.Net语言

最新文章
·VC#初学入门:第一个Windows程序
·ASP.NET 2.0-选用DataSet或DataReader
·用.net 处理xmlHttp发送异步请求
·asp.net创建文件夹的IO类的问题
·asp.net 2.0 中加密web.config 文件中的配置节
·关于ASP.NET调用JavaScript的实现
·如何实现ASP.NET网站个性化
·Acegi安全系统的配置-.NET教程,评论及其它
·Spring安全系统:Acegi Security Acegi简介-.NET教程,评论及其它
·Biztalk 开发之 架构和实例的验证-.NET教程,评论及其它


 
 


版权申明:本站文章均来自网络,如有侵权,请联系我们,我们收到后立即删除,谢谢!

特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有。
  打印  刷新  关闭
返回首页 |关于我们 | 联系我们 | 付款方式 | 创业联盟 | 虚拟主机 | 资讯中心 | 友情链接 | 网站地图

版权所有 西部数码(www.west263.com)
CopyRight (c) 2002~2006 west263.com all right reserved.
公司地址:四川成都市万和路90号天象大厦4楼 邮编:610031
电话总机:028-86262244 86263048 86263408 86263960 86264018 86267838
售前咨询:总机转201 202 203 204 206 208
售后服务:总机转211 212 213 214
财务咨询:总机转224 223 传真:028-86264041 财务QQ:点击发送消息给对方635483282
售前咨询QQ:点击发送消息给对方2182518 点击发送消息给对方241975952 点击发送消息给对方275026793 点击发送消息给对方408235859
售后服务QQ:点击发送消息给对方17708515 点击发送消息给对方307742704 点击发送消息给对方287976517 点击发送消息给对方363783715
《中华人民共和国增值电信业务经营许可证》编号:川B2-20030065号