ASP.NET中新的ListView控件為顯示和CURD資料庫操作提供了基于模闆的布局,使之成為一項極好的方式,建立以資料為中心的Web應用程式。
當你編寫以使用者為中心的應用程式時,總需要某種形式的資料集,起碼來說,你需要從一個資料源如關系資料庫或XML檔案檢索資料,在顯示給使用者之前先要進行格式化,盡管ASP.NET之前的版本就提供了以資料為中心的顯示控件如GridView,這些控件缺乏專業Web開發人員需要的可自定義和可擴充特性,為了解決這個問題,ASP.NET3.5提供了一個新的控件ListView,它提供了非常優秀的自定義和擴充特性,使用這些特性,你可以以任何格式顯示資料,使用模闆和樣式,同時用最少的代碼執行CURD(建立、讀取、更新、删除)操作。
本文主要集中于使用新的ListView控件時資料通路步驟,同時還包括進階特性如編輯資料和處理事件。
ListView控件入門
ASP.NET提供的大部分資料綁定控件都是使用額外的标記自動封裝顯示資料,舉例來說,GridView控件在一個HTML表格(<table>)中顯示它的資料,每條記錄顯示一行(<tr>),每個字段顯示為一個單元格(<td>),雖然你可以使用TemplateField元件自定義GridView的外觀,但GridView的輸出仍然是限制在一個table元件中的,但有時候你想要完全控制由資料綁定控件産生的HTML标記的外觀,這正是ListView控件的優勢,ListView控件不是使用額外的标記來封裝它的輸出内容,而是靠你指定的精确的HTML描述,使用ListView控件内置的模闆就可以指定精确的标記,表1列出了ListView控件支援的模闆。
模闆
用途
AlternatingItemTemplate
交替項目模闆
用不同的标記顯示交替的項目,便于檢視者差別連續不斷的項目
EditItemTemplate
編輯項目模闆
控制編輯時的項目顯示
EmptyDataTemplate
空資料模闆
控制ListView資料源傳回空資料時的顯示
EmptyItemTemplate
空項目模闆
控制空項目的顯示
GroupSeparatorTemplate
組分隔模闆
控制項目組内容的顯示
GroupTemplate
組模闆
為内容指定一個容器對象,如一個表行、div或span元件
InsertItemTemplate
插入項目模闆
使用者插入項目時為其指定内容
ItemSeparatorTemplate
項目分隔模闆
控制項目之間内容的顯示
ItemTemplate
項目模闆
控制項目内容的顯示
LayoutTemplate
布局模闆
指定定義容器對象的根元件,如一個table、div或span元件,它們包裝ItemTemplate或GroupTemplate定義的内容。
SelectedItemTemplate
已選擇項目模闆
指定目前選中的項目内容的顯示
最關鍵的兩個模闆是LayoutTemplate和ItemTemplate,正如名字暗示的那樣,LayoutTemplate為ListView控件指定了總的标記,而ItemTemplate指定的标記用于顯示每個綁定的記錄,例如:下面的代碼顯示了在ListView中由HTML table控制的一串項目。
<asp:ListView ID="..." runat="server" DataSourceID="...">
<LayoutTemplate>
<table …….>
<tr runat="server" ID="itemPlaceholder"></tr>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr>
<td><%# Eval("Name") %></td>
</tr>
</ItemTemplate>
</asp:ListView>
在前面的代碼中,LayoutTemplate标記内的<tr>标記的ID是設定項目占位符(itemPlaceHolder),它告訴ListView通過<table>内的ItemTemplate産生的内容要放到什麼地方,這就是為什麼你需要單獨定義LayoutTemplate和ItemTemplate模闆的原因。
你已經看到LisView控件支援的多個模闆了,下一步是要建立一個簡單的web站點,名字就叫做ListViewExample(你可以從http://assets.devx.com/sourcecode/38579_tt_mainsource.zip下載下傳該站點的示例代碼),建立好web站點後,選擇Web站點?添加新項目,添加一個新的ASP.NET頁面,名字命名為SimpleListView.aspx(見清單1),這個頁面将使用ListView控件從AdventureWorks示例資料庫中的Product表顯示産品資料。
清單1.ListView控件示例清單
<%@ Page Language="C#" %>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<link rel="Stylesheet" type="text/css" href="StyleSheet.css" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" />
<title>Simple Data Binding Example using ListView control</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ListView runat="server" ID="productsView"
DataSourceID="productSource" DataKeyNames="ProductID">
<LayoutTemplate>
<table cellpadding="2" runat="server" id="tblProducts"
style="width:460px">
<tr runat="server" id="itemPlaceholder">
</tr>
</table>
<asp:DataPager runat="server" ID="DataPager" PageSize="3">
<Fields>
<asp:NumericPagerField ButtonCount="10"
PreviousPageText="<--" NextPageText="-->" />
</Fields>
</asp:DataPager>
</LayoutTemplate>
<ItemTemplate>
<tr id="row" style="height:72px" runat="server">
<td valign="top" class="ProductInfo">
Product ID : <asp:Label ID="lblProductID" runat="server"
Text='<%#Eval("ProductID") %>' />
<br />
Name : <asp:Label ID="lblName" runat="server"
Text='<%#Eval("Name") %>' />
<br />
Product Number : <asp:Label ID="lblProductNumber"
runat="server" Text='<%#Eval("ProductNumber") %>' />
</td>
</tr>
</ItemTemplate>
<ItemSeparatorTemplate>
<tr id="separator" style="height:10px" runat="server">
<td>--------------------------------------------------------
------------------</td>
</tr>
</ItemSeparatorTemplate>
<EmptyDataTemplate>
There are no products!
</EmptyDataTemplate>
</asp:ListView>
<asp:SqlDataSource id="productSource" runat="server"
DataSourceMode="DataSet"
ConnectionString="<%$ ConnectionStrings:AdventureWorks%>"
SelectCommand="SELECT ProductID,Name,ProductNumber,
Color,ListPrice FROM Production.Product">
</asp:SqlDataSource>
</div>
</form>
</body>
</html>
在清單1中,SqlDataSource通過設定ConnectionString 和SelectCommand 屬性控制從AdventureWorks資料庫的Product表中檢索資料,ConnectionString屬性通過一個ASP.NET表達式從web.config檔案擷取連接配接字元串,在我的測試機上,連接配接字元串定義在web.config中,如:
<connectionStrings>
<add name="AdventureWorks"
connectionString="server=localhost;uid=sa;
pwd=thiru;database=AdventureWorks;"/>
</connectionStrings>
設定好SqlDataSource屬性後,下一步是通過ListView控件顯示資料,下面是在LayoutTemplate模闆中的标記:
<LayoutTemplate>
<table cellpadding="2" runat="server" id="tblProducts"
style="width:460px">
<tr runat="server" id="itemPlaceholder">
</tr>
</table>
<asp:DataPager runat="server" ID="DataPager" PageSize="3">
<Fields>
<asp:NumericPagerField ButtonCount="10"
PreviousPageText="<--" NextPageText="-->" />
</Fields>
</asp:DataPager>
</LayoutTemplate>
LayoutTemplate模闆定義了ListView控件輸出内容的容器,除了在ListView控件頂層定義了table外,LayoutTemplate模闆還定義了<asp:DataPager>,它為ListView控件提供了分頁功能,DataPager讓你可以為任何資料綁定控件實作IpageableItemContainer進行資料分頁并顯示導航控制。
有兩種方法使資料分頁(DataPager)和資料綁定(data-bound)聯合使用:
1、設定DataPager 的PagedControlID屬性為data-bound的名字。
2、将DataPager置于data-bound層次體系之下,對于ListView控件,你可以将DataPager置于LayoutTemplate元件内。
設定DataPager的PageSize屬性,它控制每頁顯示的資料行數,你也可以在頁面送出到伺服器時通過設定QueryStringField屬性實作。
在DataPager内,你指定NumericPageField模闆,它可以讓使用者輸入一個頁号,然後按照頁号進行跳轉,如:
<asp:NumericPagerField ButtonCount="10"
PreviousPageText="<--"
NextPageText="-->" />
ItemTemplate元件為每個記錄的明細提供了标記。圖1顯示了在浏覽器中導航到該頁面的輸出。

圖1.ListView示例:通過資料綁定ListView控件到SqlDataSource控件檢索Product表中部分資料産生的輸出
用ListView控件編輯資料
正如你所看到的,使用ListView控件顯示資料相對要直接得多,但你還可以讓使用者在ListView中直接編輯資料,添加一個新頁面ListViewEditExample.aspx,它的代碼如清單2所示。
清單2.編輯ListView
<%@ Page Language="C#" %>
<script runat="server">
void deptsView_ItemUpdated(object sender,
ListViewUpdatedEventArgs e)
{
lblResult.Text = e.AffectedRows.ToString() +
" row(s) successfully updated";
}
void deptsView_PagePropertiesChanged(object sender, EventArgs e)
{
//Set the text to empty when navigating to a different page
lblResult.Text = "";
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<link rel="Stylesheet" type="text/css" href="StyleSheet.css" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" />
<title>Editing Data using ListView Control</title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:ListView ID="ContactsListView" DataSourceID="deptSource"
DataKeyNames="DepartmentID" runat="server"
OnItemUpdated="deptsView_ItemUpdated"
OnPagePropertiesChanged="deptsView_PagePropertiesChanged">
<LayoutTemplate>
<table cellpadding="2" width="640px"
runat="server" id="tblProducts">
<tr id="row1" runat="server" class="header">
<th id="header2" runat="server">Name</th>
<th id="header3" runat="server">Group Name</th>
<th id="header1" runat="server">Action</th>
</tr>
<tr runat="server" id="itemPlaceholder" />
</table>
<asp:DataPager runat="server" ID="deptsDataPager"
PageSize="3">
<Fields>
<asp:NextPreviousPagerField ShowFirstPageButton="True"
ShowLastPageButton="True" FirstPageText="|<< "
LastPageText=" >>|" NextPageText=" > "
PreviousPageText=" < " />
</Fields>
</asp:DataPager>
</LayoutTemplate>
<ItemTemplate>
<tr id="row2" runat="server">
<td>
<asp:Label ID="lblName" runat="Server"
Text='<%#Eval("Name") %>' />
</td>
<td valign="top">
<asp:Label ID="lblGroupName" runat="Server"
Text='<%#Eval("GroupName") %>' />
</td>
<td>
<asp:LinkButton ID="btnEdit" runat="Server" Text="Edit"
CommandName="Edit" />
</td>
</tr>
</ItemTemplate>
<EditItemTemplate>
<tr style="background-color: #ADD8E6">
<td>
<asp:TextBox ID="txtName" runat="server"
Text='<%# Bind("Name") %>'
MaxLength="50" /><br />
</td>
<td>
<asp:TextBox ID="txtGroupName" runat="server" Text='<%#
Bind("GroupName") %>' MaxLength="50" /><br />
</td>
<td>
<asp:LinkButton ID="btnUpdate" runat="server"
CommandName="Update" Text="Update" />
<asp:LinkButton ID="btnCancel" runat="server"
CommandName="Cancel" Text="Cancel" />
</td>
</tr>
</EditItemTemplate>
</asp:ListView>
<asp:SqlDataSource ID="deptSource" runat="server"
ConnectionString="<%$ ConnectionStrings:AdventureWorks %>"
SelectCommand="SELECT [DepartmentID],[Name],[GroupName] FROM
HumanResources.Department" UpdateCommand="UPDATE
HumanResources.Department SET Name = @Name,
GroupName = @GroupName WHERE DepartmentID = @DepartmentID">
</asp:SqlDataSource>
<br /><br />
<asp:Label runat="server" ID="lblResult" Text=""
Font-Bold="true" />
</div>
</form>
</body>
</html>
清單2的代碼說明了如何使用EditItemTemplate元件在編輯模式下生成内容,然後通過SqlDataSource更新資料庫。
首先,你設定SqlDataSource的UpdateCommand屬性,這樣SQL語句就會用由使用者指定的最新值執行資料庫更新操作。
<asp:SqlDataSource ID="deptSource" runat="server"
ConnectionString="<%$ ConnectionStrings:AdventureWorks %>"
SelectCommand="SELECT [DepartmentID],[Name],[GroupName] FROM
HumanResources.Department" UpdateCommand="UPDATE
HumanResources.Department SET Name = @Name,
GroupName = @GroupName WHERE DepartmentID = @DepartmentID">
</asp:SqlDataSource>
接下來,在ItemTemplate元件中,指定編輯項目的連接配接使用者:
<ItemTemplate>
----
----
<asp:LinkButton ID="btnEdit" runat="Server" Text="Edit"
CommandName="Edit" />
</td>
</tr>
</ItemTemplate>
然後,指定EditItemTemplate聲明使用者輸入更新的部門名稱或組名的文本框,以及送出或取消目前操作的使用者連接配接。
<EditItemTemplate>
<tr style="background-color: #ADD8E6">
<td>
<asp:TextBox ID="txtName" runat="server"
Text='<%# Bind("Name") %>'
MaxLength="50" /><br />
</td>
<td>
<asp:TextBox ID="txtGroupName" runat="server" Text='<%#
Bind("GroupName") %>' MaxLength="50" /><br />
</td>
<td>
<asp:LinkButton ID="btnUpdate" runat="server"
CommandName="Update" Text="Update" />
<asp:LinkButton ID="btnCancel" runat="server"
CommandName="Cancel" Text="Cancel" />
</td>
</tr>
</EditItemTemplate>
這裡通過CommandName屬性定義的LinkButton的行為,如表2所示。
表2. LinkButton CommandName屬性值:列出了ListView控件支援的CommandName屬性值
值
描述
Cancel
取消目前操作
Delete
從資料源删除目前選中的項目
Edit
切換ListView到編輯模式,顯示EditItemTemplate元件中指定的内容
Insert
作為一條新記錄将資料儲存到資料源
Update
用指定的值更新資料源
在更新結束後,ListView控件激活一個OnItemUpdated事件,你可以用它向使用者提供執行的狀态,在清單2的代碼中,ListView控件處理兩個事件:
1、OnItemUpdated:正如名字所暗示的那樣,這個事件允許你在更新操作完畢後執行一個自定義的程式,在前面的代碼中,這個事件被用于通知使用者影響的記錄條數。
2、OnPagePropertiesChanged:當頁面屬性發生改變時ListView控件激活這個事件,前面代碼中使用這個事件清除了在lable标記包括的文本。
如果你導航到該頁面,你會看到如圖2所示的頁面:
圖2.在運轉中編輯ListView:配置ListView控件為每條記錄顯示一個編輯連接配接,點選編輯連接配接切換到編輯模式
當你點選了編輯(Edit)超連結後,ListView控件使用EditItemTemplate顯示文本框,使用者就可以編輯文本框中的内容了,如圖3所示:
圖3.編輯模式:在編輯模式下,EditItemTemplate元件産生文本框,使用者可以在這裡輸入要更新的值
注意在編輯模式下右邊的更新(Update)和取消(Cancel)連結,當你點更新連結就會将所做的改變儲存到資料庫中,代碼使用了OnItemUpdated事件顯示更新操作所影響的行數,如圖4所示:
圖4.影響的記錄:更新結束時,顯示更新操作影響的資料行數
以上就是ListView的全部關鍵特性了,同時你也看到了一個使用ListView控件的簡單以資料驅動的示例web頁面,以及更複雜的更新功能,最後,描述了如何使用ListView控件産生的事件,正如你看到的,ListView控件擴充了運作時自定義的特性,更加适合你的需要。
注:本文示例代碼下載下傳位址http://assets.devx.com/sourcecode/38579_tt_mainsource.zip