使用DataList控件

使用DataList控件 

本章内容:

Ø 
1 、理解事件冒泡

Ø 
2 、使用模板

Ø 
3 、在DataList中显示数据

Ø 
4 、在DataList中创建多列

Ø 
5 、捕获DataList控件中产生的事件

Ø 
6 、选择DataList中的项

Ø 
7 、使用DataList控件中的DataKeys集合

Ø 
8 、编辑DataList中的项

本章介绍在ASP.NET框架中功能最强大的两个控件(DataList控件和DataGrid控件)之一的DataList控件。我们将深入探讨DataList控件,学习如何使用该控件显示数据以及编辑数据库数据。

一、理解事件冒泡 

在ASP.NET框架包含三个支持事件冒泡的标准控件:Repeater、DataList和DataGrid控件。这些控件可以让你捕获其子控件的时间。当子控件产生一个事件时,事件就“冒泡”传给包含该子控件的容器控件,并且容器控件就可以执行一个子程序来处理该事件。

二、使用模板 

在前一章中我们已经介绍过Repeater控件的五个模板(ItemTemplate、AlternationgItemTemplate、SeparatorTemplate、HeaderTemplate、FooterTemplate),可以格式化控件的输出。在DataList控件中除了支持Repeater控件中的五个模板以外,还支持如下两个模板:

1 、SelectedItemTemplate:控制如何格式化被选定的项

2 、EditItemTemplate:控制如何格式化被编辑的项。

当选定DataList中选中一个项时(即DataList的SelectedIndex属性值为当前选定项的索引值),将显示SelectedItem模板,当在DataList中选择一个项来编辑(即DataList的EditItemIndex属性值为当前选定项的索引值)时,将显示EditItem模板。

三、在DataList中显示数据: 

可以像Repeater控件那样来用DataList显示数据库表中的记录。但是,与Repeater控件不同的是:DataList控件的默认行为是在HTML表格中显示数据库记录。

如下程序清单演示如何显示pubs数据库中authors表中的数据。

<% @ Page Language = " C# " %>

<% @ Import Namespace = " System.Data.SqlClient "   %>

< script runat = server >

void  Page_Load(Object sender , EventArgs e) 

{

SqlConnection conn;

SqlCommand cmd;

SqlDataReader dr;

conn 
= new SqlConnection( "Server=localhost; Database=Pubs;uid=cdd;psw=123" );

cmd 
= new SqlCommand( "Select au_fname From authors", conn );

conn.Open();

dr 
= cmdSelect.ExecuteReader();

DataList1.DataSource 
= dr;

DataList1.DataBind();

dr.Close();

conn.Close();

}


</ Script >

< html >

< head >< title > DataList.aspx </ title ></ head >

< body >

< form Runat = " Server " >

< asp:DataList

ID
= " DataList1 "

Runat
= " Server " >

< ItemTemplate >  

<% #DataBinder.Eval(Container.DataItem,  " au_fname "  ) %>  

</ ItemTemplate >  

</ asp:DataList >

</ form >

</ body >

</ html >

在DataList中显示记录时,authors表中每行都显示在独立的HTML表格中,只要你愿意,也可以修改其RepeatLayout属性把DataList的项显示在HTML的
< div ></ div > 中。在默认情况下,RepeatLayout属性值为Table。如果把RepeatLayout属性设为Flow,那么每个项就显示在 < div ></ div > 中。

< asp:DataList RepeatLayout = ”Flow” Runat = ”Server” >

当RepeatLayout属性为Table时,通过设置GridLines属性可以在每个单元格周围显示线条。GridLines属性可选值有: Both 
/  Horizontal  /  Vertical

四、在DataList中创建多列 

DataList的一个好处的特征是可以以多个列显示数据现。通过设置其RepeatColumns和RepeatDirection属性,可以控制DataList的列的布局。

RepeatColumns属性决定要显示的列的数量。比如,如果要在DataList中显示四列的项,那么可以把这个属性设为4。

RepeatDirection属性句顶列是按水平或垂直方向来重复。在默认情况下,RepeatDirection值为Vertical,因此,如果RepeatColumns值为4,则列就像这样显示:

Column 
1  Column3 Column5 Column7 

Column 
2  Column4 Column6 Column8 

如果把RepeatDirection设为Horizontal,而且RepeatColumns值为4,那么列就像这样显示:

Column 
1  Column3 Column5 Column7 

Column 
2  Column4 Column6 Column8 

注意,即使RepeatDirection值为Vertical,还是显示为4个列。RepeatColumns永远是指重复的列的数量,而不是行的数量。 

五、捕获DataList控件中产生的事件 

正如第一小节中提到的那样,DataList控件支持事件冒泡,可以捕获DataList内包含的控件产生的事件,并且通过普通的子程序处理这些事件。讲到这里有些人可能不太明白事件冒泡的好处所在,这样,我们反过来思考:如果没有事件冒泡,那么对于DataList内包含的每一个控件产生的事件都需要定义一个相应的处理函数,如果DataList中包含10000个控件呢?或者更多呢?那我们得写多少个事件处理程序。所以有了事件冒泡,不管DataList中包含多少个控件,我们只需要一个处理程序就可以了。DataList控件支持五个事件:

1 ) EditCommand:由带有CommandName = ”edit”的子控件产生

2 ) CancelCommand:由带有CommandName = ”cancel”的子控件产生

3 ) UpdateCommand:由带有CommandName = ”update”的子控件产生

4 ) DeleteCommand:由带有CommandName = ”delete”的子控件产生

5 ) ItemCommand:DataList的默认事件

有了这五个事件,那么当我点击了DataList控件中的某一个按钮的时候,应该触发哪一个事件呢?什么时候才触发它们呢?在ASP.NET中有三个控件带有CommandName属性,分别是Button、LinkButton和ImageButton,可以设置它们的CommandName属性来表示容器控件内产生的时间类型。比如,如果设置DataList中的一个LinkButton的CommandName属性为“update”,那么点击此按钮的时候,将会触发DataList的CancelCommand事件,我们可以将相关处理代码写到对应的事件处理程序中去。 

如下程序清单演示了点击DataList中三个CommandName分别为edit、delete、update的LinkButton按钮。当点击不同的按钮时,在DataList中产生不同的事件,执行不同的程序:

<% @ Page Language = " C# "   %>  

<% @ Import Namespace = " System.Data.SqlClient "   %>  

< script runat = server >  

void  Page_Load(Object sender , EventArgs e) 



if (! IsPostBack ) 

SqlConnection conn; 

SqlCommand cmd; 

SqlDataReader dr; 

conn 
= new SqlConnection( "Server=localhost; Database=Pubs;uid=cdd;psw=123" ); 

cmd 
= new SqlCommand( "Select au_fname From authors", conn ); 

conn.Open(); 

dr 
= cmd.ExecuteReader(); 

dlstTitles.DataSource 
= dr; 

dlstTitles.DataBind(); 

dr.Close(); 

conn.Close(); 

}
 

}
 

void  DataList1_ItemCommand(  object  s, DataListCommandEventArgs e ) 

lblMessage.Text 
= "<li>Item Command!"

}
 

void  DataList1_EditCommand(  object  s, DataListCommandEventArgs e ) 

lblMessage.Text 
+= "<li>Editing Item!"

}
 

void  DataList1_DeleteCommand(  object  s, DataListCommandEventArgs e ) 

lblMessage.Text 
= "<li>Deleting Item!"

}
 

void  DataList1_UpdateCommand(  object  s, DataListCommandEventArgs e ) 

lblMessage.Text 
= "<li>Updating Item!"

}
 

</ Script >  

< html >  

< head >< title > DataListEvents.aspx </ title ></ head >  

< body >  

< form Runat = " Server " >  

< asp:Label 

ID
= " lblMessage "  

BackColor
= " yellow "  

Runat
= " Server "   />  

< p >  

< asp:DataList 

ID
= " DataList1 "  

OnItemCommand
= " DataList1_ItemCommand "  

OnEditCommand
= " DataList1_EditCommand "  

OnDeleteCommand
= " DataList1_DeleteCommand "  

OnUpdateCommand
= " DataList1_UpdateCommand "  

GridLines
= " Both "  

CellPadding
= " 4 "  

Runat
= " Server " >  

< ItemTemplate >  

<% #DataBinder.Eval(Container.DataItem,  "  au_fname  "  ) %>  

< br >  

< asp:LinkButton 

Text
= " Edit! "  

CommandName
= " edit "  

Runat
= " Server " />  

< asp:LinkButton 

Text
= " Delete! "  

CommandName
= " delete "  

Runat
= " Server " />  

< asp:LinkButton 

Text
= " Update! "  

CommandName
= " update "  

Runat
= " Server " />  

</ ItemTemplate >  

</ asp:DataList >  

</ form >  

</ body >  

</ html >  

在DataList中显示的三个LinkButton控件分别与相应的程序相关联。当点击名为delete的LinkButton控件的时候,就触发DataList控件DeleteCommand事件,该事件与DataList1_DeleteCommand函数相关联。 

大家注意到与DataList关联的函数都带有一个DataListCommandEventArgs的参数。该阐述表示从DataList传递给该函数的信息。DataListCommandEventArgs具有如下属性: 

Ø CommandArgument:表示来自于产生该事件的控件的CommandArgument属性值。 

Ø CommandName:表示产生该事件的命令名称。 

Ø CommandSource:表示产生该事件的DataList控件。 

Ø Item:表示来自DataList的项。就是DataList中发生事件的那一项。该属性非常有用,在后面的章节中会经常使用到! 

六、选择DataList中的项 

在第一小节中我们讲到DataList控件比Repeater控件多两个模板,SelectedItemTemplate模板可以格式化DataList中被选定的项的格式。 

数据绑定到DataList后,DataList中的每一项都有一个索引号,第一项的索引为0,依次往下编号。我们可以利用索引来确定DataList中具体的项。 

DataList默认以ItemTemplate或ItemTemplate
+ AlternatingItemTemplate模板显示数据项,当DataList的SelectedIndex属性(该属性默认值为 - 1 ,表示不显示SelectedItemTemplate模板)的值为DataList某一项的索引的时候,对应的项将会以SelectedItemTemplate模板显示。

如下程序清单使用DataList来显示一列来自于Authors数据库表中的作者的姓。每个作者的姓作为一个LinkButton控件呈现。当选择一个作者时,被选定的作者就使用SelectedItemTemplate来显示。

<% @ Page Language = " C# "   %>  

<% @ Import Namespace = " System.Data.SqlClient "   %>  

< script runat = server >  

void  Page_Load(Object sender , EventArgs e) 



if (! IsPostBack) 



BindDataList(); 

}
 

}
 

void  BindDataList() 

SqlConnection conn; 

SqlCommand cmd; 

SqlDataReader dr; 

conn 
= new SqlConnection("Server=localhost; Database=Pubs;uid=cdd;psw=123" ); 

cmd 
= new SqlCommand( "Select au_lname From Authors", conn ); 

conn.Open(); 

dr 
= cmd.ExecuteReader(); 

dlstAuthors.DataSource 
= dr; 

dlstAuthors.DataBind(); 

dr.Close(); 

conn.Close(); 

}
 

void  DataList1_ItemCommand(  object  s, DataListCommandEventArgs e ) 

dlstAuthors.SelectedIndex 
= e.Item.ItemIndex; 

BindDataList(); 

}
 

</ Script >  

< html >  

< head >< title > DataListSelected.aspx </ title ></ head >  

< body >  

< form Runat = " Server " >  

< asp:DataList 

ID
= "  DataList1 "  

OnItemCommand
= "  DataList1_ItemCommand "  

Runat
= " Server " >  

< ItemTemplate >  

< asp:LinkButton 

Text
= ' <%#DataBinder.Eval(Container.DataItem, "au_lname" )%> '  

Runat
= " Server "   />  

</ ItemTemplate >  

< SelectedItemTemplate >  

< b >< i ><% #DataBinder.Eval(Container.DataItem,  " au_lname "  ) %></ i ></ b >  

</ SelectedItemTemplate >  

</ asp:DataList >  

</ form >  

</ body >  

</ html >  

上面代码中DataList1.SelectedIndex 
=  e.Item.ItemIndex语句:表示把被选项的索引赋值给DataList控件的SelectedIndex属性。然后调用BindDataList()进行数据的重新绑定。 

答疑:在一次课上,讲解ItemCommand事件和DeleteCommand事件的时候,有学生问我为什么每次点了CommandName为“delete”的按钮的时候ItemCommand事件也被触发了呢?因为我平时写程序的时候没注意这个问题,一下子还真把我难住了! 回办公室后反复做了实验(通过打开页面的Trace跟踪,在相应的事件里用Trace.Warn()方法输出),最后得出结论: 

Ø ItemCommand事件是DataList控件产生的默认事件,任何DataList控件中CommandName为delete
/ cancel / update / edit的按钮被点击后,首先触发的是ItemCommand事件,然后才是相应的事件。 

Ø 但是当DataList控件中存在一个普通按钮,点击后触发ItemCommand事件,假设执行功能为选择当前项,此时如果点击了CommandName为edit的按钮,将当前项显示为编辑状态。这个时候并没有出现当前行既被选中又被编辑的情形,这和以上的结论(先触发ItemCommand事件)好象相违背。事实上这并不矛盾,因为DataList控件中的项同一时刻只能显示一个EditItemTemplate或SelectedItemTemplate模板,所以执行过程应该是这样的。点击了CommandName为edit的按钮后首先触发了ItemCommand事件,将当前的项显示为SelectedItemTemplate模板,然后再触发EditCommand事件,将当前的项显示为EditItemTemplate模板,覆盖了前面已经显示的SelectedItemTemplate模板,只不过因为速度太快,肉眼看不出这个过程而已! 

七、使用DataList控件中的DataKeys集合 

在选择DataList中的一个项时,通常需要获取与这个项相关联的主键的值。可以使用DataKeys集合来获取与一个项想关联的主键的值。 

假设要在DataList中显示一个名为Authors的数据库表,其中包含两个名为au_id和au_fname的列,当拥护选择DataList中的一个项时,你要提取与被选项相关联的au_id列的值,要实现这个操作,则需要设置DataList控件的DataKeyField属性: 

< asp:DataList

ID
= " DataList1 "

DataKeyField
= " au_id "

OnItemCommand
= " DataList1_ItemCommand "

Runat
= " Server " >

如果把数据库表的主键类的名称赋值给DataKeyField属性,那么当绑定DataList到Authors的数据表时,一个名为DataKeys的特殊集合就自动生成了。DataKeys集合包含来自数据库表的所以的主键值,起顺序与DataList中的项相同。 

注意:只有当所使用的数据表具有单个主键列时,才可以使用DataKeys集合。也就是说不能使用联合主键。 

在创建了DataKeys集合后,就可以通过传递项的索引值给DataKeys集合来获取DataList中与相关项关联的主键值。比如,要获取由DataList显示的第三项的主键值,就可以是使用语句:DataList1.DataKeys[
2 //  DataList1为DataList控件的ID值 

如果要在DataList控件的事件处理函数中发生事件的项的主键值,则可以使用语句:DataList1.DataKeys[e.Item.ItemIndex] 
//  DataList1为DataList控件的ID值 

八、编辑DataList中的项 ★★★★★ 

可以使用DataList控件来编辑数据表中的某一条记录,如下图,事实上,在DataList中完成这样的操作非常的方便,不像在asp中需要在多个页面中来回切换。 

DataList控件具有一个名为EditItemTemplate的模板,可以在EditItemTemplate中放置表单控件,以便能在DataList中编辑特定的项。当DataList的EditItemIndex属性(该属性默认值为
- 1 ,表示不显示EditItemTemplate模板)的值为DataList某一项的索引的时候,对应的项将会以EditItemTemplate模板显示。

注意:在DataList中一次只能有一个项被选定来编辑。 

如下程序清单演示了如何编辑DataList的项,其中最主要的部分就是UpdateCommand事件的处理程序,因为DataList并不会替你处理更新数据表的操作,你必须自己编写所有的代码: 

<% @ Page Language = " C# "   %>  

<% @ Import Namespace = " System.Data.SqlClient "   %>  

< script runat = server >  

void  Page_Load(Object sender , EventArgs e) 



if (! IsPostBack ) 

BindDataList(); 

}
 

}
 

void  BindDataList() 

SqlConnection conn; 

SqlCommand cmd; 

SqlDataReader dr; 

conn 
= new SqlConnection("Server=localhost; Database=Pubs;uid=cdd;psw=123" ); 

cmd 
= new SqlCommand( "Select au_id, au_lname, phone From Authors Order by au_lname", conn ); 

conn.Open(); 

dr 
= cmd.ExecuteReader(); 

DataList1.DataSource 
= dr; 

DataList1.DataBind(); 

dr.Close(); 

conn.Close(); 

}
 

void  DataList1_EditCommand(  object  s, DataListCommandEventArgs e ) 

DataList1.EditItemIndex 
= e.Item.ItemIndex; 

BindDataList(); 

}
 

void  DataList1_CancelCommand(  object  s, DataListCommandEventArgs e ) 

DataList1.EditItemIndex 
= -1

BindDataList(); 

}
 

void  DataList1_DeleteCommand(  object  s, DataListCommandEventArgs e ) 

SqlConnection conn; 

string strDelete; 

SqlCommand cmdDelete; 

string strAuthorID; 

strAuthorID 
= DataList1.DataKeys[(int)e.Item.ItemIndex].ToString(); 

conn 
= new SqlConnection("Server=localhost; Database=Pubs;uid=cdd;psw=123" ); 

strDelete 
= "Delete Authors Where au_id=@authorID"

cmdDelete 
= new SqlCommand( strDelete, conn ); 

cmdDelete.Parameters.Add( 
"@authorID", strAuthorID ); 

conn.Open(); 

cmdDelete.ExecuteNonQuery(); 

conn.Close(); 

DataList1.EditItemIndex 
= -1

BindDataList(); 

}
 

void  DataList1_UpdateCommand(  object  s, DataListCommandEventArgs e ) 

SqlConnection conn; 

string strUpdate; 

SqlCommand cmdUpdate; 

string strAuthorID; 

strAuthorID 
= DataList1.DataKeys[(int)e.Item.ItemIndex].ToString(); 

TextBox txtLastName 
= (TextBox)e.Item.FindControl( "txtLastName" ); 

TextBox txtPhone 
= (TextBox)e.Item.FindControl( "txtPhone" ); 

conn 
= new SqlConnection("Server=localhost; Database=Pubs;uid=cdd;psw=123" ); 

strUpdate 
= "Update Authors set au_lname=@lastname, phone=@phone Where au_id=@authorID"

cmdUpdate 
= new SqlCommand( strUpdate, conn ); 

cmdUpdate.Parameters.Add( 
"@authorID", strAuthorID ); 

cmdUpdate.Parameters.Add( 
"@lastname", txtLastName.Text ); 

cmdUpdate.Parameters.Add( 
"@phone", txtPhone.Text ); 

conn.Open(); 

cmdUpdate.ExecuteNonQuery(); 

conn.Close(); 

DataList1.EditItemIndex 
= -1

BindDataList(); 

}
 

</ Script >  

< html >  

< head >< title > DataListEdit.aspx </ title ></ head >  

< body >  

< form Runat = " Server " >  

< asp:DataList 

ID
= " DataList1 "  

DataKeyField
= " au_id "  

OnEditCommand
= " DataList1_EditCommand "  

OnCancelCommand
= " DataList1_CancelCommand "  

OnDeleteCommand
= " DataList1_DeleteCommand "  

OnUpdateCommand
= " DataList1_UpdateCommand "  

RepeatColumns
= " 4 "  

GridLines
= " Both "  

CellPadding
= " 10 "  

EditItemStyle
- BackColor = " lightgrey "  

Runat
= " Server " >  

< ItemTemplate >  

<% #DataBinder.Eval(Container.DataItem,  " au_lname "  ) %>  

-   <% #DataBinder.Eval(Container.DataItem,  " phone "  ) %>  

< br >  

< asp:LinkButton 

Text
= " Edit! "  

CommandName
= " edit "  

Runat
= " Server "   />  

</ ItemTemplate >  

< EditItemTemplate >  

< b > Last Name: </ b >  

< br >  

< asp:TextBox 

ID
= " txtLastName "  

Text
= ' <%#DataBinder.Eval(Container.DataItem, "au_lname" )%> '  

Runat
= " Server "   />  

< p >  

< b > Phone: </ b >  

< br >  

< asp:TextBox 

ID
= " txtPhone "  

Text
= ' <%#DataBinder.Eval(Container.DataItem, "phone" )%> '  

Runat
= " Server "   />  

< p >  

< asp:LinkButton 

Text
= " Update! "  

CommandName
= " update "  

Runat
= " Server "   />  

< asp:LinkButton 

Text
= " Delete! "  

CommandName
= " delete "  

Runat
= " Server "   />  

< asp:LinkButton 

Text
= " Cancel! "  

CommandName
= " cancel "  

Runat
= " Server "   />  

</ EditItemTemplate >  

</ asp:DataList >  

</ form >  

</ body >  

</ html >  

运行以上程序,点击其中某一项中的edit按钮的时候,将触发DataList控件的EditCommand事件,通过执行语句DataList1.EditItemIndex 
=  e.Item.ItemIndex;将当前项显示为EditItemTemplate模板,在EditItemTemplate模板中点击cancel按钮的时候,将触发DataList控件的CancelCommand事件,通过执行语句DataList1.EditItemIndex  =   - 1 ; 将当前项恢复显示为ItemTemplate模板; 

当点击update按钮的时候,将触发DataList控件的UpdateCommand事件,在UpdateCommand事件的处理程序中,我们需要取得当前项对应的主键值及修改之后的值才能够完成更新,通过执行语句DataList1.DataKeys[(
int )e.Item.ItemIndex].ToString();来获取当前主键值(前提是指定了DataList1的DataKeyField属性值为主键字段),由于DataKeys集合返回数据类型为object类型,我们还需要调用其ToString()方法来转换成字符串类型。通过执行语句(TextBox)e.Item.FindControl(  " txtLastName "  )来获得更新后的au_lname的值,FindControl(”控件ID”)方法通过检索当前项中包含的特定ID的控件,其返回值类型为Control类型,所以还需要强制将其转换为TextBox类型,如果没有找到该ID的控件,则返回0,最后通过取得的主键值和更新后的字段的值更新数据库表。最后不要忘了重新绑定一下,否则数据库里最新的数据将不会显示出来。 

( 如果要在更新前对更新后的数据进行验证,则可以在EditItemTemplate模板中加入验证控件进行验证。)
 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值