ASP.NET 數據綁定控件介紹

儘管有豐富、功能強大的編程接口,ASP.NET 1.x DataGrid 控件仍需要編寫大量自定義代碼來處理普通操作,如分頁、排序、編輯和刪除數據。例如,當用戶單擊以保存或取消更改時,DataGrid 控件能夠引發事件但不提供更多的功能。如果要將更改存儲到持續媒介(如一個數據庫)之中,則必須自己處理 UpdateCommand 事件,檢索更改後的值,編寫一條 SQL 命令,然後從該處提交更新。

DataGrid 控件限制普通數據操作的引發事件,因爲它是一個數據源不可知的控件,能夠綁定到任何可枚舉的數據對象。執行數據操作(如更新或刪除)需要直接連接到一個特定的數據源。在 ASP.NET 1.x 中,則通過編寫特定於應用程序的 ADO.NET 代碼解決這個問題的。

ASP.NET 2.0 改進了數據綁定體系結構,引入了新的系列組件(數據源對象)作爲數據綁定控件與 ADO.NET 對象之間的橋樑。這些源對象提升了一個略爲不同的編程模型,提供了新功能和新成員。您的 ASP.NET 2.0 應用程序應該使用最新的網格控件 — GridView,顯示數據報告。與之相似的 DataGrid 控件仍然支持,但 DataGrid 不能充分利用數據源組件的特定功能。

GridView 控件是 DataGrid 的接替者,並從幾個方面擴展了後者的功能。首先,它完全支持數據源組件,能夠自動處理諸如分頁、排序和編輯等數據操作,前提是綁定的數據源對象支持這些操作。另外,GridView 控件有一些比 DataGrid 優越的功能上的改進。特別是,它支持多個主鍵字段,公開了一些用戶界面的改進功能和一個處理與取消事件的新模型。

GridView 附帶了一對互補的視圖控件:DetailsView 和 FormView。通過這些控件的組合,您能夠輕鬆地建立主/詳細視圖,而只需少量代碼,有時根本不需要代碼。

GridView 與 DataGrid


ASP.NET 2.0 中數據綁定控件的類層次結構比 ASP.NET 1.x 中的更一致。在 2.0 版本中,所有控件無論有什麼樣的實際實現過程和用戶界面特點,均從同一個基類(BaseDataBoundControl 類)派生。圖 1 顯示新的類關係圖。DataGrid 和其他 1.x 版本的控件(如 Repeater 和 DataList)沒有包含在該關係圖中。這些現有控件的繼承樹與 ASP.NET 1.x 的相同。特別是,Repeater 繼承了 WebControl,而 DataList 和 DataGrid 繼承了 BaseDataList。如圖 1 所示,GridView 是一個複合數據綁定控件,它與其他所有數據綁定控件(包括 DropDownList、DetailsView 和 ListBox)共享一組方法和屬性。


按此在新窗口打開圖片
圖 1 ASP.NET 類關係圖


GridView 和 DataGrid 控件的高級功能相似,但基礎卻不同。GridView 儘可能地保留了 DataGrid 的對象模型,以便輕鬆地從現有頁面進行移植。但是,基於 DataGrid 的代碼與新的基於 GridView 的代碼不可能 100% 兼容。

DataGrid 與 GridView 控件的另一個主要差異在於自適應用戶界面。與 1.x 版本的 DataGrid 不同的是,GridView 也能在移動設備上顯示。換句話說,您能夠使用相同的用於桌面頁面的網格控件在移動設備上生成報告。2.0 版本的 DataGrid 也能自適應地顯示,但是它的 UI 功能沒有 GridView 豐富。

在 ASP.NET 2.0 中,改進後的 DataGrid 控件支持諸如主題和個性化等通用的控件功能。此外,新的 DataGrid 控件可由一個數據源控件填充。但要記住,綁定到數據源對象的 DataGrid 只能用於讀取數據。要實際修改底層數據源,仍然需要一些用戶定義的代碼。而 GridView 控件可以利用底層數據源的功能並自動刪除或更新記錄。注意,GridView 控件也支持傳統的基於 DataSource 屬性和 DataBind 方法的綁定機制。儘管完全支持這種綁定機制,但是不鼓勵使用這樣的編程實踐方法。


GridView 和數據源控件


那麼,數據源控件是什麼?我在 2004 年 6 月一期的 MSDN®Magazine 中詳細介紹了 ASP.NET 2.0 的這項流行的新功能。簡言之,一個數據源控件就是一組 Microsoft® .NET Framework 類,它有利於數據存儲和數據綁定控件之間的雙向綁定。現有的控件(如 DataGrid)以及新的數據綁定控件(如 GridView),儘管綁定能力不同,但都能綁定到一個數據源。

一個數據源控件代表了數據源的主要功能:選擇、插入、更新和刪除。數據源控件能代表任何數據源:從關係數據源庫到 XML 文件,從流數據到業務對象。如果簡要介紹能讓您想起 .NET 的託管提供程序,請參見圖 2。


按此在新窗口打開圖片
圖 2 數據源控件、GridView 和數據源


數據源控件可以位於一些 .NET 數據提供程序的上層,在數據綁定控件和數據源之間形成一箇中間層。數據源控件也會公開一個提供基本操作的公共接口。一些數據綁定控件 — 特別是 GridView 控件,將這些命令與其他與數據有關的操作一起,綁定到適當的自動編輯。

數據源控件通過其屬性和方法,將綁定內容以一組命名的視圖形式公開。IDataSource 接口提供從數據源檢索數據視圖的基本功能集,所有數據源控件都實現了這個接口。ASP.NET 2.0 提供一些內置數據源控件,如圖 3 所列。圖 3列出的數據源控件屬於兩類:列表和分層組件。SiteMapDataSource 和 XmlDataSource 組件是分層數據源控件,用於像 TreeView 和 Menu 控件這樣的分層組件。其他各種組件用於管理列表數據。

圖 4 中的代碼說明如何在一個示例頁面上將 GridView 和 DataGrid 綁定到同一個數據源控件。在 ASP.NET 2.0 中,這是推薦的數據綁定方法。SqlDataSource 控件的特點是一個 ConnectionString 屬性加上 SelectCommand、UpdateCommand、InsertCommand 和 DeleteCommand 屬性的任意組合。所有屬性都是字符串形式,並且引用帶有可選參數的命令文本: 

<asp:SqlDataSource runat="server" 
  ID="MySource" 
  ConnectionString="SERVER=(local);
  DATABASE=northwind;Integrated Security=SSPI;"
  SelectCommand="SELECT * FROM employees WHERE employeeid > @MinID">
  <SelectParameters>
     <asp:ControlParameter Name="MinID" 
          ControlId="EmpID" 
          PropertyName="Text" />
  </SelectParameters>
</asp:SqlDataSource>
 

每個數據源控件由唯一的 ID 表示。ID 是連結數據綁定控件和數據源控件之間的紐帶。通過 DataSourceId 屬性將 GridView 綁定到一個數據源控件。例如,每當網格需要獲取數據時,就執行與 SQLDataSource 控件相關聯的 SelectCommand SQL 命令。當網格需要更新或刪除一條記錄時,就執行相應的 UpdateCommand 或 DeleteCommand SQL 命令。如果不存在這樣的命令,則引發一個異常。在內部,當用戶刪除或更新一條記錄時,GridView 就像 1.x 版本的 DataGrid 一樣引發事件。但是與 DataGrid 不同的是,GridView 爲這些事件定義內部的處理程序。默認的處理程序檢索綁定數據源定義的命令來處理和執行這些操作。圖 4說明,在保持網格顯示或更新數據的標記後無需編寫代碼。在更復雜的情況下,您可能需要編寫一些代碼。


按此在新窗口打開圖片
圖 5 GridView 和 DataGrid


數據源控件和 GridView 控件通常用於無代碼數據綁定。圖 5 顯示圖 4的代碼生成的輸出結果。

在 ASP.NET 2.0 中,除了 DataSource 和 DataMember,DataGrid 還公開了 DataSourceId 屬性。DataSourceId 屬性將 DataGrid 連接到同一頁面上定義的一個合法數據源對象。但是,DataGrid 不提供與 GridView 同一級別的自動化操作。當用戶單擊以更新一條記錄時,DataGrid 引發 UpdateCommand 事件,而 GridView 除了引發 Updating 和 Updated 事件外,還檢索和執行數據源更新命令,允許用戶自定義發送到數據源控件的信息。


GridView 對象模型


GridView 與 DataGrid 的整體結果看起來相似。一些通用元素經過了重命名,一些通用功能現在需要不同的語法。總之,如果熟悉 DataGrid 控件,則可立即自如地運用 GridView。圖 6 詳盡列出了組成 GridView 的新元素(請注意,其中一些元素,如 DetailLinkStyle,僅用於在移動設備上顯示網格)。行元素通過 Rows 集合中的 GridViewRow 類生成的實例進行顯示。GridViewRow 類映射到 DataGridItem 類,而 Rows 明確替代了 DataGrid 的項目集合。行類型由 DataControlRowType 枚舉表示,用來指示位置和角色(例如,頁腳、頁眉、頁導航和數據行)。GridView 還引入一個新概念 — 行元素狀態。該行狀態由 DataControlRowState 標記的枚舉值表示 — 通常值是 Edit,可選值爲 Insert 和 Selected。有趣的是,這兩類枚舉恰巧由所有數據視圖控件(GridView、DetailsView 和 FormView)共享。

除了引入符合自適應顯示的元素之外,GridView 僅有一個其他類型的新元素 — 空數據行。當 GridView 綁定到一個空數據源時,會選擇性地顯示一些默認內容,爲用戶提供反饋。在這種情況下顯示的內容依賴於新的空數據行元素的內容。可通過一個屬性 (EmptyDataText) 或一個模板 (EmptyDataTemplate) 設置該行的內容。

GridView 控件的屬性主要分爲三種類型:行爲、可視設置和狀態。圖 7 列出 GridView 的一些屬性。請查看包括 EnableSortingAndPagingCallbacks、EmptyDataText 和 UseAccessibleHeader 在內的新屬性以及被重命名或改編的屬性,後者實現了 DataGrid 已經支持的功能。

編程模型與按鈕列略有不同。在 ASP.NET 1.x 的 DataGrid 中,您不得不通過添加特定的列類型來創建一個 Edit 按鈕 — EditCommandColumn。如果要創建一個 Delete 或 Select 按鈕列,則必須添加通用的按鈕列並預定義一個命令名。GridView 對象則更一致、更簡潔。它基於三個新的布爾屬性:AutoGenerateEditButton、AutoGenerateDeleteButton 和 AutoGenerateSelectButton。當其中任何一個屬性設置爲真時,網格中分別添加一個 Edit、Delete 或 Select 命令按鈕列。例如,當 AutoGenerateEditButton 屬性設置爲真時,在網格中自動爲每個數據行添加帶有 Edit 按鈕的一列。也可以手動添加這些按鈕,方法是在列集合中添加一個 CommandField 對象。Columns 屬性列出了列對象,這些對象很像 DataGrid 的 Columns 屬性列出的對象。根據客戶的反饋,其中也添加了幾個幫助器屬性。特別是,您現在能夠爲每個顯示行存儲多個鍵值。實際上,DataGrid 的 DataKeyField 字符串屬性已經擴展爲一個字段名數組。新的屬性命名爲 DataKey,用於存儲由字段名組成的一個字符串數組,這個字符串數組唯一標識一個數據行。DataKey 是特定行的值的相應數組。它返回 DataKey 對象的集合。每個 DataKey 對象包含一個鍵名值,DataKey 的 DataKey 對象數量與 GridView 的顯示行數相同。

SortDirection 和 SortExpression 跟蹤當前的網格排序。這些屬性用於在內部實現自動翻轉排序,標記網格當前排序次序。每個對象的 PagerSettings 組包含配置用戶界面、行爲和頁導航位置的所有屬性。現在,頁導航支持的導航模式不但包括首行和尾行,還包括下一行和上一行。

GridView 控件也能夠使用一個基於回調的輕量型機制來進行排序和分頁。您可以通過設置 EnableSortingAndPagingCallbacks 布爾屬性來開啓和關閉此功能。當單擊排序或分頁鏈接來啓用回調時,GridView 請求排序數據或下一頁,不回發可視頁面。(這裏發生了一個往返過程,但是無頁面刷新,因此您不知道。)請注意,這個功能有個警告:啓用 GridView 中的選項時,新頁面保留當前選定的索引。如果有與之相關聯的詳細信息頁面,那麼選定的內容將失去同步。處理類似 PageIndexChanging 這樣的事件也不管用,因爲如果不啓用回調,則不能引發這些事件。最後,切記回調驅動的分頁和排序機制需要使用 Microsoft Internet Explorer 5.0 及更高版本。


GridView 事件


GridView 控件使用的方法與我們熟知的 DataBind 方法不同。在 ASP.NET 2.0 中,許多控件以及 Page 類本身使用的是 Pre-load/Post-load 事件對。控件生命週期中的關鍵操作被包裝在一對事件中,一個在操作發生前觸發,另一個在操作完成後立即觸發。GridView 類也是這樣。圖 8 顯示的是新事件列表。使用事件來通告操作極大地增強了編程能力。例如,通過掛鉤 RowUpdating 事件,您能夠檢查新值的更新內容。您可能想在客戶端提供的值存留到下層數據存儲之前,通過 HTML 編碼來處理 RowUpdating 事件。這種簡單的技巧有助於避免惡意的腳本注入。

使用 pre/post 事件對使您能夠取消一個基於運行時條件而進行的事件。請看以下代碼片段: 

void PageIndexChanging(object sender, GridViewPageEventArgs e)
{
  // Is this the sensitive page? (> 4)
  bool isSensitivePage = (e.NewPageIndex > 4);
  if (isSensitivePage && (User.Identity.Name != "username"))
     e.Cancel = true;
  return;    
}

取消是一個讀/寫布爾屬性,存在於所有從 CancelEventArgs 派生的事件參數類中。GridView 的許多事件參數類繼承了 CancelEventArgs,這意味着所有這些事件都能被取消。Cancel 屬性值在激發“pre”事件時通常設置爲假。處理事件時,您能夠檢查一些條件,通過將 Cancel 屬性設置爲真選擇取消事件。例如,剛纔的代碼片段在當前用戶未被授權查看索引大於 4 的頁面時,取消了轉換到新頁面的操作。 


顯示、排序和分頁


一個網格通常用於顯示數據庫查詢的結果。使用 GridView 控件顯示結果比以往更簡單。您只需建立一個數據源對象,提供連接字符串和查詢文本,爲 GridView 的 DataSourceId 屬性分配數據源 ID。運行時,GridView 自動綁定到數據源,生成正確的數據列。在默認情況下,查詢的所有列均顯示在網格中。

像 DataGrid 控件一樣,GridView 也支持在 Columns 集合中自定義列字段。如果只想顯示檢索到的數據字段的一個子集,或只想自定義其顯示外觀,則可使用代表顯示數據列的對象來填充 Columns 集合。GridView 支持多種列類型,包括新的複選框和圖像列類型: 

<columns>
  <asp:boundfield datafield="productname" headertext="Product" /> 
  <asp:checkboxfield datafield="discontinued" 
     headertext="Discontinued" /> 
  <asp:buttonfield buttontype="Button" text="Buy" /> 
  <asp:hyperlinkfield text="More Info..." 
     datanavigateurlfields="productid,discontinued"
     datanavigateurlformatstring="more.aspx?id={0}&disc={1}" /> 
</columns>
 

圖 9 顯示的活動網格配置爲使用代碼中列出的字段。GridView 列類名與 DataGrid 接口中的相應類名略有不同。後綴“column”基本被替換成後綴“field”。除了名字的更改,與列類匹配的行爲幾乎相同。一些新的列類型使您不必經常使用模板。例如,CheckBoxField 列通過一個複選框顯示特定的數據字段,而改進的 HyperLinkField 列提供了期待已久的功能 — 支持多個 URL 參數。正如剛纔的代碼片段所示,DataNavigateUrlFields 屬性接收了一個以逗號分隔的字段名列表,並將其合併到 DataNavigateUrlFormatString 屬性的文本中。 

按此在新窗口打開圖片
圖 9 帶有活動字段的 GridView


請注意 ButtonField 與 CommandField 之間的差異。兩列都向網格的用戶界面添加了一個按鈕,但是 CommandField 用於顯示命令按鈕來執行選擇、編輯、插入或刪除操作。ButtonField 只是代表作爲按鈕顯示的字段。最後,GridView 能夠通過 ImageField 列類型嵌入圖像。 

<asp:imagefield datafield="photo" headertext="Picture" />

圖 10 顯示活動的 ImageField 列,它位於 Northwind 僱員表的照片字段。有趣的是,ImageField 通過 ASP.NET 2.0 DynamicImage 控件顯示來自數據庫和 URL 兩者的圖像。而且,在編輯模式下,ImageField 列彈出一個 Browse 按鈕,用於定位要上載的位於本機的新文件。 


按此在新窗口打開圖片
圖 10 圖像字段列


Template 列也受支持,所需的語法與 ASP.NET 1.x 的 DataGrid 使用的相似: 

<asp:templatefield headertext="Product">
   <itemtemplate>
     <b><%# Eval("productname")%></b> <br />
     available in <%# Eval("quantityperunit")%>
  </itemtemplate>
</asp:templatefield>
 

有趣的是,ASP.NET 2.0 允許的數據綁定表達式的語法更簡潔。在 ASP.NET 1.x 中生成模板化的內容需要使用下列表達式: DataBinder.Eval(Container.DataItem, "fieldname")由於使用了一個更小的數據綁定機制,現在,您能夠避免使用 DataBinder 類中靜態的 Eval 方法,而是調用 Page 類定義的新的 Eval 保護方法。您將計算的字段名和方法傳遞給 Eval,決定當前的數據項並通過 DataBinder.Eval 準備一個常規調用。 

Eval 被聲明爲 TemplateControl 類的一個保護方法,Page 和 UserControl 都從這個類派生。真正代表一個 .aspx 活動頁面的類是從 Page 派生的一個類的實例;因此,它能夠調入受保護的方法。ASCX 用戶控件也是如此。

如果焦點是顯示純數據,則不需要像 GridView 這樣全新的網格控件。當然,現在您只需少量代碼或不需要編碼就能將數據源控件綁定到 GridView,但是單憑這點就有必要替換 DataGrid 嗎?如果答案是否定的,請考慮排序和分頁。

在 GridView 控件中,只需通過開啓 AllowPaging 和 AllowSorting 屬性就能啓用自動翻轉排序和分頁功能。如果在 ASP.NET 1.x 中嘗試過這項操作,您就可大概瞭解這項功能了。

按此在新窗口打開圖片
圖 11 活動的可分頁、可排序網格


圖 11 顯示一個可分頁、可排序的網格。圖 12 顯示此網格的完整代碼。(值得注意的是,僅當需要標記列標頭來指示排序方向時才需要使用 C# 代碼。)因此,無需編寫代碼,排序和分頁就能十分正常地運行。通過 DataSourceMode 屬性控制 SQLDataSource 的數據檢索模型。可行的值類型是 DataSet(默認值)和 DataReader。當 DataSourceMode 爲 DataSet 時,數據源控件可能會一直選擇性地緩存 SELECT 命令的結果。這使得 GridView 適應於豐富多樣的使用情境,其中控件可提供無代碼排序、篩選和分頁功能。默認情況下禁用緩存,因此它必須在數據源控件上啓用。

在內存中緩存數據能大大提高性能,但是數據會顯得有些脆弱。您必須權衡利弊,因爲如果系統內存運行效率低,Cache 對象會自動丟棄最少使用的數據。此外,在 ASP.NET 2.0 中,SQLDataSource 控件可能選擇性地建立與數據庫的自動依賴關係,以便立即檢測到數據變更。這確保了總是顯示最新的數據。有關數據源控件功能的更多信息,請參見我在前面提到的 2004 年 6 月發表的文章。當 SQLDataSource 控件檢索模型爲 DataReader 時,檢索數據使用 IDataReader 對象,它是一個只進、只讀、流水遊標。


編輯數據


DataGrid 控件最大的缺點之一 — 相反卻是 GridView 控件最大的優點之一,是處理數據源更新的能力。當綁定數據源支持更新時,GridView 能夠自動執行數據操作,從而提供真正的出盒解決方案。數據源控件通過一些布爾屬性(例如 CanUpdate、CanDelete、CanSort 等)提供這些功能。

對 GridView 控件而言,數據編輯意味着就地編輯和記錄刪除。如前所述,就地編輯指網格支持更改當前顯示記錄的功能。啓用 GridView 的就地編輯,需要啓動 AutoGenerateEditButton 布爾屬性: 

<asp:gridview runat="server" id="MyGridView" 
   datasourceid="MySource" 
   autogenerateeditbutton="true">
   &S226;&S226;&S226;
</asp:gridview>


當 AutoGenerateEditButton 屬性設置爲真時,GridView 顯示附加的一列,如圖 13 中最左邊一列。單擊一行的 Edit 按鈕將此行置於編輯模式下。當一行處於編輯模式下時,非只讀行的每個綁定字段將顯示適當的輸入控件,通常是一個 TextBox。當您單擊更新時,GridView 引發 RowUpdating 事件並檢查數據源的 CanUpdate 屬性。如果 CanUpdate 返回值爲假,則引發一個異常。否則,在數據源對象的 UpdateCommand 屬性後創建和配置一個命令對象。

按此在新窗口打開圖片
圖 13 GridView 的 Edit 列


即使您對 SQL 的操作僅限於定義命令結構 — 只定義語句而讓控件來完成其他操作,也無需使用 ADO.NET 或擔心如何使用命令或連接。想在用戶單擊 Update 時保留更改,可編寫以下代碼: 

<asp:sqldatasource runat="server" id="MySource" 
   connectionstring="SERVER=...;DATABASE=northwind;Integrated 
   Security=SSPI;"
   updatecommand="UPDATE employees SET
           firstname=@firstname, lastname=@lastname 
           WHERE employeeid=@employeeid">
</asp:sqldatasource>
<asp:gridview runat="server" id="MyGridView" 
   DataSourceId="MySource" 
   DataKeyNames="employeeid" AutoGenerateEditButton="true">
   &S226;&S226;&S226;
</asp:gridview>


數據源的 UpdateCommand 屬性被設置爲 GridView 使用的 SQL 命令。您能夠使用所需的任意數量的參數。如果您採用一種特殊的命名規則,參數值也能夠自動解析。代表更新字段的參數(例如 firstname)必須與網格列的 DataField 屬性名相匹配。用於標識工作記錄的 WHERE 子句中使用的參數必須與 DataKeyNames 屬性匹配,後者是顯示記錄的關鍵字段。最後,考慮這種情況:如果沒有定義 UpdateCommand,卻提交更改,那麼 CanUpdate 返回值爲假,並引發一個異常。RowUpdated 事件發出信號通知更新命令結束。通過更新命令更新的行數可在 RowUpdated 事件參數的 AffectedRows 屬性中檢索。

GridView 自動收集輸入字段的值,填充 name/value 對詞典,這個詞典指示了每個行字段的新值。GridView 也公開一個 RowUpdating 事件,允許您修改正在傳遞到數據源對象的值。此外,在相關數據源上激發 Update 操作前,GridView 將自動調用 Page.IsValid。如果 Page.IsValid 返回值爲假,將取消操作。這對使用包括驗證程序在內的自定義編輯模板特別有用。

行刪除操作方式與此相似。下面的 SQL 命令是一個數據源對象的 DeleteCommand 屬性的合法內容: 

DELETE employees WHEREemployeeid=@employeeid請注意,如果由於特定於數據庫的約束而無法刪除記錄,刪除操作將失敗。例如,如果子記錄通過某種關係引用父記錄,父記錄將無法刪除。在這種情況下,引發一個異常。 

GridView 控件不自動支持向數據源插入數據。沒有這項功能完全是由於實現 GridView 不依賴於底層數據源的功能和特性。實際上,數據源對象提供一個 CanInsert 屬性並支持一個 InsertCommand 屬性。請注意,通過 GridView 和 DetailsView 控件的組合能夠實現這個功能,一會您就會了解到。


DetailsView 控件


許多應用程序需要一次作用於一條記錄。在 ASP.NET 1.x 中,沒有內置的功能支持這種情況。創建單條記錄視圖是可能的,但需要您自己編寫代碼。首先,您需要獲取記錄,然後,將字段綁定到數據綁定表單,選擇性地提供分頁按鈕來瀏覽記錄。我編寫了三個 Cutting Edge 列的安裝程序來解決這個問題 — 2002 年 4 月、5 月和 6 月。

當生成主/詳細視圖時,經常需要顯示單條記錄的內容。通常,用戶從網格中選擇一條主記錄,讓應用程序追溯所有可用字段。通過組合 GridView 和 DetailsView,編寫少量代碼,就能夠生成有層次結構的視圖。

DetailsView 控件能夠自動綁定到任何數據源控件,使用其數據操作集。控件能夠自動分頁、更新、插入和刪除底層數據源的數據項,只要數據源支持這些操作。多數情況下,建立這些操作無需編寫代碼,如下所示: 

<asp:detailsview runat="server" id="det" 
   datasourceid="MySource" 
   autogenerateeditbutton="true"
   autogenerateinsertbutton="true"
   autogeneratedeletebutton="true"
   allowpaging="true"
   headertext="Employees">
   <pagersettings mode="NextPreviousFirstLast"
      firstpageimageurl="images/first.gif" 
      lastpageimageurl="images/last.gif" 
      nextpageimageurl="images/next.gif" 
      previouspageimageurl="images/prev.gif" /> 
</asp:detailsview>
 

DetailsView 控件的用戶界面能夠通過使用數據字段和類型進行自定義,其方式與 GridView 相似。DetailsView 不支持自定義模板,因爲這項特殊的功能完全構造在新的 FormView 控件中。DetailsView 具有一個命令欄,顯示 Edit、Delete 和 New 按鈕的任意組合。當您單擊 Edit 或 New 時,控件顯示 Edit 或 Insert 模式,字段內容顯示在文本框中。工作模式能通過 Mode 和 DefaultMode 屬性控制。 

使用 DetailsView 控件能很好地實現無需代碼的主/詳細視圖。除了 Edit 和 Delete 按鈕,GridView 控件支持 Select 按鈕,它也是預定義的。通過設置 AutoGenerateSelectButton 屬性爲真,您能爲每一行啓用此按鈕。當用戶單擊此按鈕時,當前行輸入選定狀態,爲 GridView 的 SelectedIndex 屬性分配從 0 開始的索引值。此外,GridView 控件引發 SelectedIndexChanged 事件。應用程序可以掛鉤到這個事件,並執行自定義代碼。

在 ASP.NET 2.0 中,如果您想生成主/詳細視圖,則無需處理 SelectedIndexChanged 事件。您可以將一個 GridView 控件和一個 DetailsView 控件拖放到頁面上,將兩者綁定到一個數據源。生成無代碼的主/詳細視圖的技巧是,將詳細視圖控件綁定到當前選定記錄所代表的數據源,如下所示: 

<asp:sqldatasource runat="server" id="MyDetailSource"    
   &S226;&S226;&S226;
   selectcommand="SELECT * FROM customers"
   filterexpression="customerid='@customerid'">
   <filterparameters>
     <asp:ControlParameter Name="customerid" 
        ControlId="masterGrid" 
        PropertyName="SelectedValue" />
   </filterparameters>
</asp:sqldatasource>
 

數據源對象的 FilterExpression 屬性爲 SelectCommand 指定的基礎查詢定義 WHERE 子句。參數值能夠以多種方式指定,包括直接綁定一個控件屬性。 對象將 @customerid 參數設置爲主網格控件的 SelectedValue 屬性存儲的值。圖 14 的代碼顯示如何配置主網格控件和詳細視圖控件。圖 15 顯示活動頁面。請注意,無需程序代碼來完成這些功能。


按此在新窗口打開圖片
圖 15 活動主網格



FormView 控件


FormView 是新的數據綁定控件,使用起來像是 DetailsView 的模板化版本。它每次從相關數據源中選擇一條記錄顯示,選擇性地提供分頁按鈕,用於在記錄之間移動。與 DetailsView 控件不同的是,FormView 不使用數據控件字段,而是允許用戶通過模板定義每個項目的顯示。FormView 支持其數據源提供的任何基本操作。

FormView 控件是作爲通常使用的更新和插入接口而設計的,它不能驗證數據源架構,不支持高級編輯功能,比如外鍵字段下拉。然而,使用模板來提供此功能很容易。FormView 和 DetailsView 有兩方面的功能差異。首先,FormView 控件具有 ItemTemplate、EditItemTemplate 和 InsertItemTemplate 屬性,而 DetailsView 一個也沒有。其次,FormView 缺少命令行 — 將可用功能進行分組的工具欄。與 GridView 和 DetailsView 控件不同的是,FormView 沒有其自己默認的顯示佈局。同時,它的圖形化佈局完全是通過模板自定義的。因此,每個模板都包括特定記錄需要的所有命令按鈕。下列代碼片斷是在頁面中嵌入一個 FormView 的典型寫法。 

<asp:FormView ID="EmpDetails" runat="server" 
    DataSourceId="MySource" AllowPaging="true">
    <ItemTemplate>
      &S226;&S226;&S226;
    </ItemTemplate>
    <EditItemTemplate>
      &S226;&S226;&S226;
    </EditItemTemplate>
    <InsertItemTemplate>
      &S226;&S226;&S226;
    </InsertItemTemplate>
</asp:FormView>
 

圖 16 說明一個使用 FormView 控件的頁面。Edit 按鈕通過命令名 Edit 的 <asp:Button> 元素來添加。這將導致 FormView 從只讀模式轉換到編輯模式,使用定義過的 EditItemTemplate 顯示。New 命令名將強制控件轉換爲插入模式,顯示 InsertItemTemplate 的定義內容。最後,如果您將命令名爲 Delete 的按鈕添加到項目模板中,用戶單擊它時,FormView 將調用數據源的 Delete 命令。

按此在新窗口打開圖片

按此在新窗口打開圖片
圖 16 FormView 控件


如何檢索數據來更新或插入一條記錄?您可以使用一個新的數據綁定關鍵字 Bind,它是專門爲雙向綁定而設計的: 

Bind 關鍵字像 Eval 一樣用於顯示數據,而且能在更新或插入一條記錄時檢索輸入值。此外,Bind 對 GridView 和 DetailsView 使用的 TemplateFields 非常有用。 

Bind 將綁定控件屬性值存入一個值集合,FormView 控件自動檢索和使用這個集合來組合插入或編輯命令的參數列表。傳遞到 Bind 的參數必須與數據容器的字段名匹配。例如,上一個代碼片斷中的文本框存放備註字段的值。最後,還要記住的是編輯和插入模板必須包含保存變更的按鈕。這是指普通的按鈕 — 用於保存的 Update 和 Insert 以及用於放棄操作的 Cancel。

FormView 事件的工作方式與 DetailsView 和 GridView 相同。因此,如果想處理像數據預處理或後處理(例如,填充下拉框)這樣更復雜的操作,您應該爲 ItemCommand、ItemInserting 和 ModeChanging 之類的事件編寫適當的事件處理程序。


小結


數據綁定控件是大多數 Web 應用程序的必要組成部分。數據綁定控件應該簡單但功能強大。理想的情況是,它們應該以很少的單擊操作以及有限的代碼數量提供高級的功能。雖然 ASP.NET 2.0 仍然在使用,但是其新一代的數據綁定控件滿足了這個需求。ASP.NET 1.x 數據綁定的主要缺點是需要爲普通數據操作編寫過多的代碼。這一點已經隨着數據源對象和 GridView 控件的引入而解決了。DetailsView 和 FormView 是對 GridView 的完美補充,代表了對 ASP.NET 1.x 數據工具箱的重大改進。
 

Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1488396

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章