DataList控制项是·NET中的一个控制项。DataList控制项以表的形式呈现数据,通过该控制项,您可以使用不同的布局来显示数据记录,例如,将数据记录排成列或行的形式。您可以对 DataList控制项进行配置,使用户能够编辑或删除表中的记录。(DataList控制项不使用数据源控制项的数据修改功能;您必须自己提供此代码。)DataList控制项与 Repeater 控制项的不同之处在于:DataList控制项将项显式放在HTML表中,而Repeater控制项则不然。
基本介绍
- 中文名:datalist
- 类型:控制项
- 领域:电脑技术
- 呈现形式:表
简介
DataList控制项用于显示限制于该控制项的项目的重複列表 ,其使用方式和Repeater控制项相似,也是使用模板标记。不过,DataList控制项会默认地在数据项目上添加表格,而且正是由于它使用模板进行设计,所以它的灵活性比GridView更高,DataList控制项可被绑定到资料库表、XML档案或者其他项目列表, DataList 控制项新增 SelectedItemTemplate 和 EditItemTemplate 模板标记,可以支持选取和编辑功能。
控制项使用
目录
1、理解事件冒泡
2、使用模板
3、在DataList中显示数据
4、在DataList中创建多列
5、捕获DataList控制项中产生的事件
6、选择DataList中的项
7、使用DataList控制项中的DataKeys集合
8、编辑DataList中的项
理解事件冒泡
在“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;
SqlDataReaderdr;
conn = new SqlConnection( "Server=localhost; Database=Pubs;uid=cdd;password=123" );
cmd = new SqlCommand( "Select au_fname From authors", conn );
conn.Open();
dr = cmd.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,那幺每个项就显示在<span></span>中。
<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 Column2 Column3 Column4
Column 5 Column6 Column7 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的UpdateCommand事件,我们可以将相关处理代码写到对应的事件处理程式中去。
如下程式清单演示了点击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”的按钮(触发DeleteCommand事件)的时候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/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模板中加入验证控制项进行验证。)
HTML
定义和用法
<datalist> 标籤定义选项列表。请与 input 元素配合使用该元素,来定义 input 可能的值。
datalist 及其选项不会被显示出来,它仅仅是合法的输入值列表。
请使用 input 元素的 list属性来绑定 datalist。
提示:不能控制 datalist 的位置,并且不能将其与伺服器的数据进行绑定。
HTML4.01 与 HTML5之间的差异
<datalist> 标籤是 HTML5 中的新标籤。
全局属性
accesskey、class、contenteditable、contextmenu、data-*、draggable、dir、hidden、spellcheck、style、tabindex、title
实例
<input id="myCar" list="cars" />
<datalist id="cars">
<option value="BMW">
<option value="Ford">
<option value="Volvo">
</datalist>
浏览器支持
目前只有 Firefox 和 Opera 支持 <datalist> 标籤。