在 DataList 中編輯與刪除資料的概觀 (C#)
雖然 DataList 缺少內建的編輯和刪除功能,但在本教學課程中,我們將瞭解如何建立支援編輯和刪除其基礎數據的 DataList。
簡介
在插入 、更新和刪除數據 的概觀教學課程中,我們探討如何使用應用程式架構、ObjectDataSource 和 GridView、DetailsView 和 FormView 控件來插入、更新和刪除數據。 使用 ObjectDataSource 和這三個數據 Web 控件時,實作簡單的數據修改介面是一個貼齊,而且只涉及從智慧標記勾選複選框。 不需要撰寫任何程序代碼。
不幸的是,DataList 缺少 GridView 控件固有的內建編輯和刪除功能。 當宣告式數據源控件和無程式代碼數據修改頁面無法使用時,這項遺漏的功能部分是由於 DataList 是舊版 ASP.NET 的複本。 雖然 ASP.NET 2.0 中的 DataList 不提供與 GridView 相同的現成數據修改功能,但我們可以使用 ASP.NET 1.x 技術來包含這類功能。 此方法需要一些程序代碼,但如本教學課程所示,DataList 有一些事件和屬性可協助進行此程式。
在本教學課程中,我們將瞭解如何建立支援編輯和刪除其基礎數據的 DataList。 未來的教學課程將檢查更進階的編輯和刪除案例,包括輸入字段驗證、妥善處理從數據存取或商業規則層引發的例外狀況等等。
注意
如同 DataList,重複項控件缺少插入、更新或刪除的現用功能。 雖然可以新增這類功能,但 DataList 包含重複程式中找不到的屬性和事件,可簡化新增這類功能。 因此,本教學課程和未來查看編輯和刪除的教學課程將嚴格著重於 DataList。
步驟 1:建立編輯和刪除教學課程網頁
在開始探索如何更新和刪除 DataList 中的數據之前,讓我們先花點時間在網站專案中建立 ASP.NET 頁面,我們將需要本教學課程和接下來的幾個頁面。 首先新增一個名為 EditDeleteDataList
的新資料夾。 接下來,將以下 ASP.NET 頁面新增至該資料夾,確保將每個頁面與 Site.master
母版頁相關聯:
Default.aspx
Basics.aspx
BatchUpdate.aspx
ErrorHandling.aspx
UIValidation.aspx
CustomizedUI.aspx
OptimisticConcurrency.aspx
ConfirmationOnDelete.aspx
UserLevelAccess.aspx
圖 1:新增教學課程 ASP.NET 頁面
就像在其他資料夾中一樣, Default.aspx
在 EditDeleteDataList
資料夾中列出其區段中的教學課程。 回想一下,SectionLevelTutorialListing.ascx
使用者控制項提供了此功能。 因此,透過將此用戶控制項從「解決方案資源管理器」拖曳到頁面的設計視圖來新增至 Default.aspx
。
圖 2:將 SectionLevelTutorialListing.ascx
使用者控制項新增至 Default.aspx
(按一下以檢視完整大小的影像)
最後,將頁面新增為檔案的專案 Web.sitemap
。 具體來說,使用 DataList 和 Repeater <siteMapNode>
在 Master/Detail Reports 後面新增下列標記:
<siteMapNode
title="Editing and Deleting with the DataList"
description="Samples of Reports that Provide Editing and Deleting Capabilities"
url="~/EditDeleteDataList/Default.aspx" >
<siteMapNode
title="Basics"
description="Examines the basics of editing and deleting with the
DataList control."
url="~/EditDeleteDataList/Basics.aspx" />
<siteMapNode
title="Batch Update"
description="Examines how to update multiple records at once in a
fully-editable DataList."
url="~/EditDeleteDataList/BatchUpdate.aspx" />
<siteMapNode
title="Error Handling"
description="Learn how to gracefully handle exceptions raised during the
data modification workflow."
url="~/EditDeleteDataList/ErrorHandling.aspx" />
<siteMapNode
title="Adding Data Entry Validation"
description="Help prevent data entry errors by providing validation."
url="~/EditDeleteDataList/UIValidation.aspx" />
<siteMapNode
title="Customize the User Interface"
description="Customize the editing user interfaces."
url="~/EditDeleteDataList/CustomizedUI.aspx" />
<siteMapNode
title="Optimistic Concurrency"
description="Learn how to help prevent simultaneous users from
overwritting one another s changes."
url="~/EditDeleteDataList/OptimisticConcurrency.aspx" />
<siteMapNode
title="Confirm On Delete"
description="Prompt a user for confirmation when deleting a record."
url="~/EditDeleteDataList/ConfirmationOnDelete.aspx" />
<siteMapNode
title="Limit Capabilities Based on User"
description="Learn how to limit the data modification functionality
based on the user s role or permissions."
url="~/EditDeleteDataList/UserLevelAccess.aspx" />
</siteMapNode>
更新 Web.sitemap
後,花點時間透過瀏覽器查看教學網站。 左側功能表現在包含 DataList 編輯和刪除教學課程的專案。
圖 3:網站地圖現在包含 DataList 編輯和刪除教學課程的專案
步驟 2:檢查更新和刪除數據的技術
使用 GridView 編輯和刪除數據很容易,因為 GridView 和 ObjectDataSource 會在一起運作。 如檢查與插入、更新和刪除相關的事件教學課程中所討論,按兩下數據列 [更新] 按鈕時,GridView 會自動將使用雙向數據系結的欄位指派給UpdateParameters
其 ObjectDataSource 集合,然後叫用該 ObjectDataSource s Update()
方法。
可悲的是,DataList 不提供任何此內建功能。 我們有責任確保使用者的值已指派給 ObjectDataSource s 參數,並呼叫其 Update()
方法。 為了協助我們進行這項工作,DataList 提供下列屬性和事件:
DataKeyField
更新或刪除時,我們需要能夠唯一識別 DataList 中的每個專案。 將此屬性設定為所顯示資料的主鍵欄位。 這麼做會將每個 DataList 專案的指定值填入 DataList 集合DataKeys
。DataKeyField
EditCommand
當按下 Button、LinkButton 或 ImageButton 屬性CommandName
設為 [編輯] 時,就會引發此事件。- 當按下 Button、LinkButton 或 ImageButton 屬性
CommandName
設定為 Cancel 時,就會引發此事件。CancelCommand
- 當按下 Button、LinkButton 或 ImageButton 屬性設定為 Update 時,就會
UpdateCommand
引發此事件。CommandName
DeleteCommand
當按下 Button、LinkButton 或 ImageButton 屬性CommandName
設定為 Delete 時,就會引發此事件。
使用這些屬性和事件,有四種方法可用來更新和刪除 DataList 中的數據:
- 使用 ASP.NET 1.x 技術 ,DataList 存在於 ASP.NET 2.0 和 ObjectDataSources 之前,而且能夠透過程式設計方式完全更新和刪除數據。 這項技術完全放棄 ObjectDataSource,並要求我們直接從商業規則層將數據系結至 DataList,這兩者都是在擷取要顯示的數據,以及在更新或刪除記錄時。
- 在頁面上使用單一 ObjectDataSource 控件進行選取、更新和刪除 ,而 DataList 缺少 GridView 固有的編輯和刪除功能,因此我們無法自行新增它們。 使用此方法時,我們使用 ObjectDataSource 就像在 GridView 範例中一樣,但必須為 DataList 事件
UpdateCommand
建立事件處理程式,其中我們設定 ObjectDataSource s 參數並呼叫其Update()
方法。 - 使用 ObjectDataSource 控制項進行選取,但在使用選項 2 時直接更新和刪除 BLL 時,我們需要在事件中
UpdateCommand
撰寫一些程式代碼、指派參數值等等。 相反地,我們可以繼續使用 ObjectDataSource 進行選取,但直接對 BLL 進行更新和刪除呼叫(例如選項 1)。 在我看來,透過直接與 BLL 互動來更新數據,會導致比指派 ObjectDataSource sUpdateParameters
並呼叫其Update()
方法更容易閱讀的程序代碼。 - 透過多個 ObjectDataSource 使用宣告式 Means,上述三種方法都需要一點程式代碼。 如果您寧願繼續使用盡可能多的宣告式語法,最後一個選項是在頁面上包含多個 ObjectDataSources。 第一個 ObjectDataSource 會從 BLL 擷取數據,並將它系結至 DataList。 若要更新,會新增另一個 ObjectDataSource,但會直接在 DataList s
EditItemTemplate
中新增 。 若要包含刪除支援,還需要在 中ItemTemplate
新增另一個 ObjectDataSource。 透過這種方法,這些內嵌的 ObjectDataSource 會使用ControlParameters
宣告方式將 ObjectDataSource 參數係結至使用者輸入控件(而不必以程序設計方式在 DataListUpdateCommand
事件處理程式中指定它們)。 此方法仍然需要一些程式代碼,我們需要呼叫內嵌的 ObjectDataSource sUpdate()
或Delete()
命令,但需要遠低於其他三種方法。 此處的缺點是,多個 ObjectDataSources 會雜亂無章地查看頁面,並減去整體可讀性。
如果強制只使用上述其中一種方法,我選擇選項 1,因為它提供最大的彈性,而且因為 DataList 原本是設計來容納此模式。 雖然 DataList 已擴充為使用 ASP.NET 2.0 數據源控件,但它沒有官方 ASP.NET 2.0 數據 Web 控件的所有擴充點或功能(GridView、DetailsView 和 FormView)。 不過,第2至4個選項並不值得。
本教學課程和未來的編輯和刪除教學課程將會使用 ObjectDataSource 來擷取數據,以顯示並引導對 BLL 的呼叫來更新和刪除數據(選項 3)。
步驟 3:新增 DataList 和設定其 ObjectDataSource
在本教學課程中,我們將建立列出產品資訊的 DataList,並針對每個產品,讓使用者能夠編輯名稱和價格,並完全刪除產品。 特別是,我們會擷取記錄以使用 ObjectDataSource 顯示,但會直接與 BLL 互動來執行更新和刪除動作。 在我們擔心實作 DataList 的編輯和刪除功能之前,讓我們先取得頁面,以在只讀介面中顯示產品。 由於我們已在先前的教學課程中檢查這些步驟,因此我會快速進行。
從開啟 Basics.aspx
資料夾中的頁面 EditDeleteDataList
開始,然後從 [設計] 檢視將 DataList 新增至頁面。 接下來,從 DataList 的智慧標記建立新的 ObjectDataSource。 因為我們正在使用產品數據,因此請將它設定為使用 類別 ProductsBLL
。 若要擷取 所有 產品,請選擇 GetProducts()
[SELECT] 索引卷標的 方法。
圖 4:設定 ObjectDataSource 以使用 ProductsBLL
類別 (按一下查看全尺寸影像)
圖 5:使用 GetProducts()
方法傳回產品資訊(按兩下以檢視完整大小的影像)
DataList 與 GridView 一樣,不是針對插入新數據而設計的;因此,從 [插入] 索引標籤的下拉式清單中選取 [無] 選項。此外,選擇 [更新] 和 [刪除] 索引標籤的 [無] ,因為更新和刪除將會透過 BLL 以程式設計方式執行。
圖 6:確認 ObjectDataSource s INSERT、UPDATE 和 DELETE 索引標籤標的下拉式清單已設定為 [無] (按兩下以檢視完整大小的影像)
設定 ObjectDataSource 之後,按兩下 [完成],返回設計工具。 如往範例所示,完成 ObjectDataSource 設定時,Visual Studio 會自動建立 ItemTemplate
DropDownList 的 ,並顯示每個數據欄位。 將此值 ItemTemplate
取代為只顯示產品名稱與價格的 。 此外,將 RepeatColumns
屬性設定為 2。
注意
如插入、更新和刪除資料概觀中所述,使用 ObjectDataSource 修改數據時,我們的架構需要從 ObjectDataSource 宣告式標記中移除 OldValuesParameterFormatString
屬性(或將其重設為預設值 )。 {0}
不過,在本教學課程中,我們只使用 ObjectDataSource 來擷取數據。 因此,我們不需要修改 ObjectDataSource 的 OldValuesParameterFormatString
屬性值(雖然不會造成此影響)。
以自定義的 DataList 取代預設 DataList ItemTemplate
之後,頁面上的宣告式標記看起來應該如下所示:
<asp:DataList ID="DataList1" runat="server" DataKeyField="ProductID"
DataSourceID="ObjectDataSource1" RepeatColumns="2">
<ItemTemplate>
<h5>
<asp:Label runat="server" ID="ProductNameLabel"
Text='<%# Eval("ProductName") %>'></asp:Label>
</h5>
Price: <asp:Label runat="server" ID="Label1"
Text='<%# Eval("UnitPrice", "{0:C}") %>' />
<br />
<br />
</ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
SelectMethod="GetProducts" TypeName="ProductsBLL"
OldValuesParameterFormatString="original_{0}">
</asp:ObjectDataSource>
花點時間透過瀏覽器查看我們的進度。 如圖 7 所示,DataList 會在兩個數據行中顯示每個產品的產品名稱和單價。
圖 7:產品名稱和價格會顯示在雙欄資料清單中(按兩下以檢視完整大小的影像)
注意
DataList 有一些更新和刪除程式所需的屬性,而且這些值會儲存在檢視狀態中。 因此,建置支援編輯或刪除數據的 DataList 時,必須啟用 DataList 檢視狀態。
精明的讀取器可能會記得,在建立可編輯的 GridView、DetailsViews 和 FormViews 時,我們能夠停用檢視狀態。 這是因為 ASP.NET 2.0 Web 控件可以包含 控件狀態,這是在回傳中保存的狀態,例如檢視狀態,但視為必要。
停用 GridView 中的檢視狀態只會省略一般狀態資訊,但會維護控件狀態(包括編輯和刪除所需的狀態)。 DataList 已在 ASP.NET 1.x 時間範圍內建立,不會使用控制狀態,因此必須啟用檢視狀態。 如需控件狀態用途及其與檢視狀態有何不同的詳細資訊,請參閱 控件狀態與 檢視狀態。
步驟 4:新增編輯使用者介面
GridView 控件是由字段集合所組成(BoundFields、CheckBoxFields、TemplateFields 等等)。 這些欄位可以根據其模式來調整其轉譯標記。 例如,在只讀模式中時,BoundField 會將其數據域值顯示為文字;當處於編輯模式時,它會轉譯 TextBox Web 控件,其 Text
屬性會指派數據域值。
另一方面,DataList 會使用範本轉譯其專案。 唯讀專案會使用 ItemTemplate
來轉譯,而編輯模式中的專案則透過 EditItemTemplate
轉譯。 此時,我們的 DataList 只有 ItemTemplate
。 若要支援專案層級編輯功能,我們需要新增 EditItemTemplate
,其中包含要針對可編輯項目顯示的標記。 在本教學課程中,我們將使用 TextBox Web 控件來編輯產品名稱和單價。
EditItemTemplate
可以宣告方式或透過設計工具建立 (從 DataList 智慧標記中選取 [編輯範本] 選項)。 若要使用 [編輯範本] 選項,請先按兩下智慧標記中的 [編輯範本] 連結,然後從下拉式清單中選取 EditItemTemplate
專案。
圖 8:選擇使用 DataList s EditItemTemplate
(按兩下以檢視完整大小的影像)
接下來,輸入產品名稱: 和 Price: ,然後將兩個 TextBox 控件從 [工具箱] 拖曳至 EditItemTemplate
設計工具上的介面。 將 TextBoxes ID
屬性設定為 ProductName
和 UnitPrice
。
圖 9:新增 [產品名稱] 和 [價格] 的 TextBox (單擊以檢視完整大小的影像)
我們需要將對應的產品數據域值系結至 Text
兩個 TextBox 的屬性。 從 TextBoxes 智慧標記中,按兩下 [編輯 DataBindings] 連結,然後將適當的數據欄位與 Text
屬性產生關聯,如圖 10 所示。
注意
將數據欄位系結UnitPrice
至 Price TextBox s Text
欄位時,您可以將它格式化為貨幣值 ()、一般數位 ({0:C}
{0:N}
),或保持未格式化。
圖 10:將 和 UnitPrice
數據欄位系結ProductName
至 Text
TextBoxes 的屬性
請注意圖 10 中的 [編輯 DataBindings] 對話框如何不包含 在 GridView 或 DetailsView 中編輯 TemplateField 或 FormView 中的範本時出現的雙向數據系結複選框。 雙向數據系結功能允許輸入 Web 控制項中的值自動指派給對應的 ObjectDataSource s InsertParameters
,或在 UpdateParameters
插入或更新數據時。 DataList 不支援雙向數據系結,因為我們稍後會在本教學課程中看到,在使用者進行變更並準備好更新數據之後,我們需要以程序設計方式存取這些 TextBoxes Text
屬性,並將其值傳遞至 類別中的ProductsBLL
適當UpdateProduct
方法。
最後,我們需要將 [更新] 和 [取消] 按鈕新增至 EditItemTemplate
。 如我們在主複本/詳細數據中使用具有詳細數據清單的主記錄專案符號列表教學課程中所見,當 Button、LinkButton 或 ImageButton,其CommandName
屬性是從 Repeater 或 DataList 內按兩下時,就會引發 Repeater 或 DataList s ItemCommand
事件。 針對 DataList,如果 CommandName
屬性設定為特定值,也可能引發額外的事件。 特殊 CommandName
屬性值包括:
- Cancel 會
CancelCommand
引發 事件 - Edit 會
EditCommand
引發 事件 - Update 會
UpdateCommand
引發 事件
請記住,除了 事件之外ItemCommand
,也會引發這些事件。
將 新增至 EditItemTemplate
兩個 Button Web 控制項,其中一個設定為 Update,另一 CommandName
個設定為 Cancel。 新增這兩個 Button Web 控制件之後,設計工具看起來應該如下所示:
圖 11:將 [更新] 和 [取消] 按鈕新增至 EditItemTemplate
(按兩下以檢視完整大小的影像)
EditItemTemplate
完成 DataList 的宣告式標記看起來應該如下所示:
<asp:DataList ID="DataList1" runat="server" DataKeyField="ProductID"
DataSourceID="ObjectDataSource1" RepeatColumns="2">
<ItemTemplate>
<h5>
<asp:Label runat="server" ID="ProductNameLabel"
Text='<%# Eval("ProductName") %>' />
</h5>
Price: <asp:Label runat="server" ID="Label1"
Text='<%# Eval("UnitPrice", "{0:C}") %>' />
<br />
<br />
</ItemTemplate>
<EditItemTemplate>
Product name:
<asp:TextBox ID="ProductName" runat="server"
Text='<%# Eval("ProductName") %>' /><br />
Price:
<asp:TextBox ID="UnitPrice" runat="server"
Text='<%# Eval("UnitPrice", "{0:C}") %>' /><br />
<br />
<asp:Button ID="UpdateProduct" runat="server"
CommandName="Update" Text="Update" />
<asp:Button ID="CancelUpdate" runat="server"
CommandName="Cancel" Text="Cancel" />
</EditItemTemplate>
</asp:DataList>
步驟 5:新增管道以進入編輯模式
此時,DataList 已透過其 EditItemTemplate
定義編輯介面;不過,目前沒有方法可讓使用者瀏覽我們的頁面,指出他想要編輯產品資訊。 我們需要在按下時,將 [編輯] 按鈕新增至每個產品,以編輯模式呈現該 DataList 專案。 首先,透過設計工具或以宣告方式將 [編輯] 按鈕新增至 ItemTemplate
。 請務必將 [編輯] 按鈕的 CommandName
屬性設定為 [編輯]。
新增此 [編輯] 按鈕之後,請花點時間透過瀏覽器檢視頁面。 此外,每個產品清單都應該包含 [編輯] 按鈕。
圖 12:將 [更新] 和 [取消] 按鈕新增至 EditItemTemplate
(按兩下以檢視完整大小的影像)
按兩下按鈕會造成回傳,但不會將產品清單帶入編輯模式。 若要讓產品成為可編輯的,我們需要:
- 將 DataList s
EditItemIndex
屬性 設定為剛按下 [編輯] 按鈕之 的索引DataListItem
。 - 將數據重新系結至 DataList。 重新轉譯 DataList 時,
DataListItem
其ItemIndex
對應至 DataList 的EditItemIndex
會使用其EditItemTemplate
來轉譯。
由於按兩下 [編輯] 按鈕時會引發 DataList s EditCommand
事件,因此請使用下列程式代碼建立 EditCommand
事件處理程式:
protected void DataList1_EditCommand(object source, DataListCommandEventArgs e)
{
// Set the DataList's EditItemIndex property to the
// index of the DataListItem that was clicked
DataList1.EditItemIndex = e.Item.ItemIndex;
// Rebind the data to the DataList
DataList1.DataBind();
}
EditCommand
事件處理程式會以 類型的 DataListCommandEventArgs
對象傳遞為第二個輸入參數,其中包含已按兩下其 [編輯] 按鈕的參考DataListItem
。e.Item
。 事件處理程式會先將 DataList s EditItemIndex
設定為 ItemIndex
可 DataListItem
編輯的 ,然後藉由呼叫 DataList s DataBind()
方法,將數據重新繫結至 DataList。
新增此事件處理程式之後,請重新瀏覽瀏覽器中的頁面。 按兩下 [編輯] 按鈕現在可編輯點擊的產品(請參閱圖 13)。
圖 13:按兩下 [編輯] 按鈕可編輯產品 (按兩下以檢視完整大小的影像)
步驟 6:儲存用戶變更
按兩下編輯的產品 [更新] 或 [取消] 按鈕此時不會執行任何動作;若要新增這項功能,我們需要建立 DataList 和UpdateCommand
CancelCommand
事件的事件處理程式。 從建立 CancelCommand
事件處理程序開始,這會在按兩下編輯的產品 [取消] 按鈕時執行,並負責將DataList傳回其預先編輯狀態。
若要讓 DataList 以唯讀模式轉譯其所有項目,我們需要:
- 將 DataList s
EditItemIndex
屬性 設定為不存在DataListItem
索引的索引。-1
是安全的選擇,因為DataListItem
索引從 開始0
。 - 將數據重新系結至 DataList。 由於沒有
DataListItem
ItemIndex
es 對應至 DataList sEditItemIndex
,因此整個 DataList 將會以唯讀模式轉譯。
您可以使用下列事件處理程式程式代碼來完成這些步驟:
protected void DataList1_CancelCommand(object source, DataListCommandEventArgs e)
{
// Set the DataList's EditItemIndex property to -1
DataList1.EditItemIndex = -1;
// Rebind the data to the DataList
DataList1.DataBind();
}
此外,按兩下 [取消] 按鈕會將DataList傳回其預先編輯狀態。
我們需要完成的最後一 UpdateCommand
個事件處理程式是事件處理程式。 此事件處理程式需要:
- 以程式設計方式存取使用者輸入的產品名稱和價格,以及編輯的產品 。
ProductID
- 在類別中
ProductsBLL
呼叫適當的UpdateProduct
多載,以起始更新程式。 - 將 DataList s
EditItemIndex
屬性 設定為不存在DataListItem
索引的索引。-1
是安全的選擇,因為DataListItem
索引從 開始0
。 - 將數據重新系結至 DataList。 由於沒有
DataListItem
ItemIndex
es 對應至 DataList sEditItemIndex
,因此整個 DataList 將會以唯讀模式轉譯。
步驟 1 和 2 負責儲存用戶的變更;步驟 3 和 4 會在儲存變更之後,將 DataList 傳回其預先編輯狀態,且與事件處理程式中 CancelCommand
執行的步驟相同。
若要取得更新的產品名稱和價格,我們需要使用 FindControl
方法來以程式設計方式參考 中的 EditItemTemplate
TextBox Web 控制件。 我們也需要取得編輯的產品值 ProductID
。 當我們一開始將 ObjectDataSource 系結至 DataList 時,Visual Studio 會將 DataList 的 DataKeyField
屬性指派給數據源 (ProductID
) 的主鍵值。 然後,您可以從 DataList 集合 DataKeys
擷取此值。 請花點時間確保 DataKeyField
屬性確實設定為 ProductID
。
下列程式代碼會實作四個步驟:
protected void DataList1_UpdateCommand(object source, DataListCommandEventArgs e)
{
// Read in the ProductID from the DataKeys collection
int productID = Convert.ToInt32(DataList1.DataKeys[e.Item.ItemIndex]);
// Read in the product name and price values
TextBox productName = (TextBox)e.Item.FindControl("ProductName");
TextBox unitPrice = (TextBox)e.Item.FindControl("UnitPrice");
string productNameValue = null;
if (productName.Text.Trim().Length > 0)
productNameValue = productName.Text.Trim();
decimal? unitPriceValue = null;
if (unitPrice.Text.Trim().Length > 0)
unitPriceValue = Decimal.Parse(unitPrice.Text.Trim(),
System.Globalization.NumberStyles.Currency);
// Call the ProductsBLL's UpdateProduct method...
ProductsBLL productsAPI = new ProductsBLL();
productsAPI.UpdateProduct(productNameValue, unitPriceValue, productID);
// Revert the DataList back to its pre-editing state
DataList1.EditItemIndex = -1;
DataList1.DataBind();
}
事件處理程式會從DataKeys
集合中讀取已編輯的產品ProductID
開始。 接下來,會參考 中的EditItemTemplate
兩個 TextBox,以及儲存在局部變數 productNameValue
unitPriceValue
和 Text
中的屬性。 我們使用 Decimal.Parse()
方法從 UnitPrice
TextBox 讀取值,如此一來,如果輸入的值具有貨幣符號,它仍然可以正確地轉換成 Decimal
值。
注意
如果 TextBoxes Text 屬性已指定值,則和 UnitPrice
TextBoxes 的值ProductName
只會指派給 productNameValue 和 unitPriceValue 變數。 否則,會針對變數使用的值 Nothing
,其效果是使用資料庫 NULL
值來更新數據。 也就是說,我們的程式代碼會將空字串轉換成資料庫 NULL
值,這是 GridView、DetailsView 和 FormView 控件中編輯介面的默認行為。
讀取值之後,會 ProductsBLL
呼叫 類別 s UpdateProduct
方法,並傳入產品名稱、價格和 ProductID
。 事件處理程式會使用與事件處理程式中完全相同的 CancelCommand
邏輯,將 DataList 傳回至其預先編輯狀態來完成。
當、 CancelCommand
和 UpdateCommand
事件處理程式完成時EditCommand
,訪客可以編輯產品的名稱和價格。 圖 14-16 顯示此編輯工作流程的運作情形。
圖 14:第一次瀏覽頁面時,所有產品都處於只讀模式(按兩下以檢視完整大小的影像)
圖 15:若要更新產品名稱或價格,請按兩下 [編輯] 按鈕(按兩下以檢視完整大小的影像)
圖 16:變更值之後,按兩下 [更新] 傳回唯讀模式 (按一下以檢視完整大小的影像)
步驟 7:新增刪除功能
將刪除功能新增至 DataList 的步驟與新增編輯功能的步驟類似。 簡言之,我們需要在按兩下時,將 [刪除] 按鈕新增至 ItemTemplate
:
- 透過
DataKeys
集合讀取對應產品ProductID
中的 。 - 呼叫
ProductsBLL
類別 sDeleteProduct
方法來執行刪除。 - 將數據重新系結至 DataList。
讓我們從將 [刪除] 按鈕新增至 ItemTemplate
開始。
按兩下時,即為 [編輯]、[更新] 或 [取消] 的Button CommandName
會引發DataList事件 ItemCommand
以及其他事件(例如,使用 [編輯 EditCommand
] 時也會引發事件)。 同樣地,DataList 中任何 Button、LinkButton 或 ImageButton 的 CommandName
屬性設定為 Delete,都會引發 DeleteCommand
事件(以及 ItemCommand
)。
在 中的 ItemTemplate
[編輯] 按鈕旁新增 [刪除] 按鈕,將其 CommandName
屬性設定為Delete。 新增此 Button 控件之後,DataList 的 ItemTemplate
宣告式語法看起來應該像這樣:
<ItemTemplate>
<h5>
<asp:Label runat="server" ID="ProductNameLabel"
Text='<%# Eval("ProductName") %>' />
</h5>
Price: <asp:Label runat="server" ID="Label1"
Text='<%# Eval("UnitPrice", "{0:C}") %>' />
<br />
<asp:Button runat="server" id="EditProduct" CommandName="Edit"
Text="Edit" />
<asp:Button runat="server" id="DeleteProduct" CommandName="Delete"
Text="Delete" />
<br />
<br />
</ItemTemplate>
接下來,使用下列程式代碼建立 DataList s DeleteCommand
事件的事件處理程式:
protected void DataList1_DeleteCommand(object source, DataListCommandEventArgs e)
{
// Read in the ProductID from the DataKeys collection
int productID = Convert.ToInt32(DataList1.DataKeys[e.Item.ItemIndex]);
// Delete the data
ProductsBLL productsAPI = new ProductsBLL();
productsAPI.DeleteProduct(productID);
// Rebind the data to the DataList
DataList1.DataBind();
}
按兩下 [刪除] 按鈕會導致回傳並引發DataList事件 DeleteCommand
。 在事件處理程式中,按兩下的產品值 ProductID
會從 DataKeys
集合存取。 接下來,呼叫 類別 s DeleteProduct
方法會刪除ProductsBLL
產品。
刪除產品之後,請務必將數據重新系結至 DataList (DataList1.DataBind()
),否則 DataList 會繼續顯示剛刪除的產品。
摘要
雖然 DataList 缺少一點,但按下 GridView 所享有的編輯和刪除支援,但可以透過一些簡短的程式代碼加以增強,以包含這些功能。 在本教學課程中,我們瞭解如何建立可刪除且可以編輯其名稱和價格的兩欄產品清單。 新增編輯和刪除支援是包含和EditItemTemplate
中ItemTemplate
適當的 Web 控制項、建立對應的事件處理程式、讀取使用者輸入和主鍵值,以及與商業規則層互動的問題。
雖然我們已將基本編輯和刪除功能新增至 DataList,但缺少更進階的功能。 例如,沒有輸入欄位驗證 - 如果使用者輸入太貴的價格,嘗試將太昂貴轉換成 Decimal
時,會擲回Decimal.Parse
例外狀況。 同樣地,如果在商業規則或數據存取層更新數據時發生問題,使用者就會看到標準錯誤畫面。 若未在 [刪除] 按鈕上進行任何確認,不小心刪除產品的可能性太高。
在未來的教學課程中,我們將瞭解如何改善編輯用戶體驗。
祝您程式設計愉快!
關於作者
Scott Mitchell,七本 ASP/ASP.NET 書籍的作者和 4GuysFromRolla.com 創始人,自 1998 年以來便開始使用 Microsoft Web 技術。 Scott 擔任獨立顧問、講師和作家。 他的新書是 Sams Teach Yourself ASP.NET 2.0 in 24 Hours。 您可以透過 mitchell@4GuysFromRolla.com 或他的部落格 (可以在 http://ScottOnWriting.NET 找到) 與他聯繫。
特別感謝
本教學課程系列已經過許多熱心的檢閱者檢閱。 本教學課程的主要檢閱者是 Zack Jones、Ken Pespisa 和 Randy Schmidt。 有興趣檢閱我即將推出的 MSDN 文章嗎? 如果是這樣,請留言給我 mitchell@4GuysFromRolla.com。