簡介
DataList
控制項用於顯示限制於該控制項的項目的重複列表 ,其使用方式和
Repeater控制項相似,也是使用模板標記。不過,DataList控制項會默認地在數據項目上添加表格,而且正是由於它使用模板進行設計,所以它的靈活性比
GridView更高,DataList控制項可被綁定到資料庫表、
XML檔案或者其他項目列表, DataList 控制項新增 SelectedItemTemplate 和 EditItemTemplate 模板標記,可以支持選取和編輯功能。
控制項使用
目錄
2、使用模板
3、在DataList中顯示數據
4、在DataList中創建多列
6、選擇DataList中的項
7、使用DataList控制項中的DataKeys集合
8、編輯DataList中的項
理解事件冒泡
使用模板
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;
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>
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> 標籤。