於刪除時新增用戶端確認 (VB)

作者:Scott Mitchell

下載 PDF

在到目前為止所建立的介面中,當使用者想要按兩下 [編輯] 按鈕時,使用者可能會不小心刪除數據。 在本教學課程中,我們將新增用戶端確認對話框,該對話框會在按兩下 [刪除] 按鈕時出現。

簡介

在過去數個教學課程中,我們已瞭解如何使用應用程式架構、ObjectDataSource 和數據 Web 控制項,以提供插入、編輯和刪除功能。 我們到目前為止檢查的刪除介面是由 [刪除] 按鈕所組成,當按兩下時,會導致回傳並叫用 ObjectDataSource s Delete() 方法。 方法 Delete() 接著會從商業規則層叫用已設定的方法,以將呼叫向下傳播至數據存取層,並將實際 DELETE 語句發出給資料庫。

雖然此使用者介面可讓訪客透過 GridView、DetailsView 或 FormView 控件刪除記錄,但當使用者按兩下 [刪除] 按鈕時,它缺少任何類型的確認。 如果使用者在想要按兩下 [編輯] 時不小心按兩下 [刪除] 按鈕,則會改為刪除他們要更新的記錄。 為了協助避免這種情況,在本教學課程中,我們將新增按兩下 [刪除] 按鈕時出現的用戶端確認對話方塊。

JavaScript confirm(string) 函式會將其字串輸入參數顯示為具有兩個按鈕的強制回應對話框中的文字- 確定和取消 (請參閱圖 1) 。 函 confirm(string) 式會根據按兩下按鈕 (true傳回布爾值,如果使用者按兩下 [確定],而且 false 他們按兩下 [取消]) 。

JavaScript 確認 (字串) 方法顯示強制回應,Client-Side Messagebox

圖 1:JavaScript confirm(string) 方法會顯示強制回應,Client-Side Messagebox

在表單提交期間,如果的值 false 是從用戶端事件處理程式傳回,則會取消表單提交。 使用這項功能,我們可以讓 [刪除] 按鈕的用戶端 onclick 事件處理程式傳回 對 confirm("Are you sure you want to delete this product?")的呼叫值。 如果使用者按兩下 [取消], confirm(string) 將會傳回 false,因而導致表單提交取消。 沒有回傳,將不會刪除按兩下 [刪除] 按鈕的產品。 不過,如果使用者在確認對話框中按兩下 [確定],回傳將會繼續取消刪除,且將會刪除產品。 如需這項技術的詳細資訊,請參閱 使用JavaScript s confirm() 方法來控制表單提交

如果使用範本與使用 CommandField 時,新增必要的用戶端腳本稍有不同。 因此,在本教學課程中,我們將探討 FormView 和 GridView 範例。

注意

使用用戶端確認技術,例如本教學課程中所討論的技術,假設您的使用者正在瀏覽支援 JavaScript 的瀏覽器,並啟用 JavaScript。 如果其中一個假設不適用於特定使用者,請按兩下 [刪除] 按鈕會立即造成回傳 (未顯示確認消息框) 。

步驟 1:建立支持刪除的 FormView

從將 FormView 新增至 ConfirmationOnDelete.aspx 資料夾中的頁面 EditInsertDelete 開始,將它系結至新的 ObjectDataSource,以透過 ProductsBLL 類別 s GetProducts() 方法提取產品資訊。 同時設定 ObjectDataSource,讓 ProductsBLL 類別 s DeleteProduct(productID) 方法對應至 ObjectDataSource s Delete() 方法;請確定 INSERT 和 UPDATE 索引卷標下拉式清單已設定為 ([無) ]。 最後,核取 FormView 智慧標記中的 [啟用分頁] 複選框。

這些步驟之後,新的 ObjectDataSource 宣告式標記看起來會如下所示:

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    DeleteMethod="DeleteProduct" OldValuesParameterFormatString="original_{0}"
    SelectMethod="GetProducts" TypeName="ProductsBLL">
    <DeleteParameters>
        <asp:Parameter Name="productID" Type="Int32" />
    </DeleteParameters>
</asp:ObjectDataSource>

如同過去未使用開放式並行存取的範例,請花點時間清除 ObjectDataSource s OldValuesParameterFormatString 屬性。

由於它已系結至僅支持刪除的 ObjectDataSource 控件,因此 FormView ItemTemplate 僅提供 [刪除] 按鈕,缺少 [新增] 和 [更新] 按鈕。 不過,FormView 的宣告式標記包含多餘的 EditItemTemplateInsertItemTemplate,可以移除。 請花點時間自定義 ItemTemplate ,這樣只會顯示產品數據欄位的子集。 我已將 Mine 設定為在其供應商和類別名稱上方的標題中 <h3> 顯示產品名稱 (,以及 [刪除] 按鈕) 。

<asp:FormView ID="FormView1" AllowPaging="True" DataKeyNames="ProductID"
    DataSourceID="ObjectDataSource1" runat="server">
    <ItemTemplate>
        <h3><i><%# Eval("ProductName") %></i></h3>
        <b>Category:</b>
        <asp:Label ID="CategoryNameLabel" runat="server"
            Text='<%# Eval("CategoryName") %>'>
        </asp:Label><br />
        <b>Supplier:</b>
        <asp:Label ID="SupplierNameLabel" runat="server"
            Text='<%# Eval("SupplierName") %>'>
        </asp:Label><br />
        <asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False"
            CommandName="Delete" Text="Delete">
        </asp:LinkButton>
    </ItemTemplate>
</asp:FormView>

透過這些變更,我們有一個功能完整的網頁,可讓使用者一次切換一個產品,只要按兩下 [刪除] 按鈕即可刪除產品。 圖 2 顯示我們到目前為止透過瀏覽器檢視進度的螢幕快照。

FormView 會顯示單一產品的相關信息

圖 2:FormView 會顯示單一產品的相關信息 (按兩下即可檢視全尺寸影像)

步驟 2:從 [刪除按鈕] Client-Side onclick 事件呼叫確認 (字串) 函式

建立 FormView 之後,最後一個步驟是設定 [刪除] 按鈕,如此一來,當訪客按兩下該按鈕時,就會叫用 JavaScript confirm(string) 函式。 將用戶端腳本新增至 Button、LinkButton 或 ImageButton 的用戶端 onclick 事件,可透過 使用 OnClientClick property來完成,這是 2.0 ASP.NET 的新功能。 因為我們想要傳回函 confirm(string) 式的值,所以只要將此屬性設定為: return confirm('Are you certain that you want to delete this product?');

變更之後,Delete LinkButton 的宣告式語法看起來應該像這樣:

<asp:LinkButton ID="DeleteButton" runat="server" CausesValidation="False"
    CommandName="Delete" Text="Delete"
    OnClientClick="return confirm('Are you certain you want to delete this product?');">
</asp:LinkButton>

這一切就一切了! 圖 3 顯示此確認動作的螢幕快照。 按兩下 [刪除] 按鈕會顯示 [確認] 對話框。 如果使用者按兩下 [取消],則會取消回傳,且不會刪除產品。 不過,如果使用者按兩下 [確定],則會繼續回傳,並叫用 ObjectDataSource s Delete() 方法,以刪除的資料庫記錄。

注意

傳入 JavaScript 函式的 confirm(string) 字串會以單引號分隔 (,而不是引號) 。 在 JavaScript 中,字串可以使用任一字元來分隔。 我們在這裡使用引號,讓傳入 confirm(string) 字串的分隔符不會與用於屬性值的 OnClientClick 分隔符產生模棱兩可。

按兩下 [刪除] 按鈕時,現在會顯示確認

圖 3:按兩下 [刪除] 按鈕時,現在會顯示確認 (按一下以檢視大小完整的影像)

步驟 3:在 CommandField 中設定刪除按鈕的 OnClientClick 屬性

直接在範本中使用 Button、LinkButton 或 ImageButton 時,只要設定其 OnClientClick 屬性以傳回 JavaScript confirm(string) 函式的結果,即可建立確認對話框的關聯。 不過,CommandField - 將 [刪除] 按鈕的欄位新增至 GridView 或 DetailsView - 沒有 OnClientClick 可宣告方式設定的屬性。 相反地,我們必須以程式設計方式參考 GridView 或 DetailsView 中適當的 DataBound 事件處理程式中的 [刪除] 按鈕,然後在該處設定其 OnClientClick 屬性。

注意

在適當的DataBound事件處理程式中設定 [刪除] 按鈕 s OnClientClick 屬性時,我們可以存取數據已系結至目前的記錄。 這表示我們可以延伸確認訊息,以包含特定記錄的詳細數據,例如「您確定要刪除 Chai 產品嗎?」您也可以使用數據系結語法在範本中進行這類自定義。

若要練習在 CommandField 中設定 OnClientClick [刪除] 按鈕的屬性 () ,讓我們將 GridView 新增至頁面。 將此 GridView 設定為使用 FormView 所使用的相同 ObjectDataSource 控制件。 同時將 GridView s BoundFields 限制為只包含產品名稱、類別和供應商。 最後,核取 GridView 智慧標記中的 [啟用刪除] 複選框。 這會將 CommandField 新增至 GridView 的 Columns 集合,並將其 ShowDeleteButton 屬性設定為 true

進行這些變更之後,您的 GridView 宣告式標記看起來應該如下所示:

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
    <Columns>
        <asp:CommandField ShowDeleteButton="True" />
        <asp:BoundField DataField="ProductName" HeaderText="Product"
            SortExpression="ProductName" />
        <asp:BoundField DataField="CategoryName" HeaderText="Category" ReadOnly="True"
            SortExpression="CategoryName" />
        <asp:BoundField DataField="SupplierName" HeaderText="Supplier" ReadOnly="True"
            SortExpression="SupplierName" />
    </Columns>
</asp:GridView>

CommandField 包含可從 GridView RowDataBound 事件處理程式以程式設計方式存取的單一 Delete LinkButton 實例。 參考之後,我們可以據以設定其 OnClientClick 屬性。 使用下列程式代碼建立 RowDataBound 事件的事件處理程式:

Protected Sub GridView1_RowDataBound(ByVal sender As Object, _
    ByVal e As System.Web.UI.WebControls.GridViewRowEventArgs) _
    Handles GridView1.RowDataBound

    If e.Row.RowType = DataControlRowType.DataRow Then
        ' reference the Delete LinkButton
        Dim db As LinkButton = CType(e.Row.Cells(0).Controls(0), LinkButton)

        ' Get information about the product bound to the row
        Dim product As Northwind.ProductsRow = _
            CType(CType(e.Row.DataItem, System.Data.DataRowView).Row, _
            Northwind.ProductsRow)

        db.OnClientClick = String.Format( _
            "return confirm('Are you certain you want to delete the {0} product?');", _
            product.ProductName.Replace("'", "\'"))
    End If
End Sub

此事件處理程式適用於資料列 (將具有 [刪除] 按鈕) 的數據列,並以程式設計方式參考 [刪除] 按鈕開始。 一般而言,請使用下列模式:

Dim obj As ButtonType = _
    CType(e.Row.Cells(commandFieldIndex).Controls(controlIndex), ButtonType)

ButtonType 是 CommandField - Button、LinkButton 或 ImageButton 所使用的按鈕類型。 根據預設,CommandField 會使用 LinkButtons,但是這可以透過 CommandField s ButtonType property自定義。 commandFieldIndex 是 GridView 集合Columns中 CommandField 的序數字索引,而 controlIndex 則是 CommandField 集合Controls中 [刪除] 按鈕的索引。 controlIndex 值取決於與 CommandField 中其他按鈕相對的按鈕位置。 例如,如果 CommandField 中顯示的唯一按鈕是 [刪除] 按鈕,請使用 0 的索引。 不過,如果有位於 [刪除] 按鈕之前的 [編輯] 按鈕,請使用 2 的索引。 使用 2 索引的原因是 CommandField 會在 [刪除] 按鈕之前新增兩個控件:[編輯] 按鈕,以及用來在 [編輯] 和 [刪除] 按鈕之間新增一些空間的 LiteralControl。

針對我們的特定範例,CommandField 使用 LinkButtons,而且是最左邊的欄位,其 commandFieldIndex 為 0。 由於沒有其他按鈕,但 CommandField 中的 [刪除] 按鈕,因此我們使用 controlIndex 為 0。

參考 CommandField 中的 [刪除] 按鈕之後,我們會接著擷取系結至目前 GridView 數據列之產品的相關信息。 最後,我們會將 [刪除] 按鈕 s OnClientClick 屬性設定為適當的 JavaScript,其中包含產品名稱。 由於傳入函式的 confirm(string) JavaScript 字串是使用單引號分隔,因此我們必須逸出出現在產品名稱中的任何單引號。 特別是,產品名稱中的任何單引號會以 「\'逸出」。

完成這些變更后,按兩下 GridView 中的 [刪除] 按鈕會顯示自訂的確認對話框, (請參閱圖 4) 。 如同 FormView 中的確認消息框,如果使用者按兩下 [取消回傳] 已取消,因而防止刪除發生。

注意

這項技術也可以用來以程式設計方式存取 DetailsView 中 CommandField 中的 [刪除] 按鈕。 不過,針對 DetailsView,您會為 DataBound 事件建立事件處理程式,因為 DetailsView 沒有 RowDataBound 事件。

按兩下 GridView s Delete 按鈕會顯示自定義確認對話方塊

圖 4:按兩下 GridView 的 [刪除] 按鈕會顯示 [自訂確認] 對話框 (按兩下即可檢視完整大小的影像)

使用 TemplateFields

CommandField 的其中一個缺點是,其按鈕必須透過索引來存取,而且產生的對象必須轉換成適當的按鈕類型, (Button、LinkButton 或 ImageButton) 。 使用「魔術數位」和硬式編碼類型會邀請在運行時間之前無法探索到的問題。 例如,如果您或其他開發人員在未來的某個時間點將新的按鈕新增至 CommandField (,例如編輯按鈕) 或變更 ButtonType 屬性,則現有的程式代碼仍會編譯而不會發生錯誤,但瀏覽頁面可能會造成例外狀況或非預期的行為,視您的程式代碼撰寫方式和所做的變更而定。

替代方法是將 GridView 和 DetailsView s CommandFields 轉換成 TemplateFields。 這會針對 CommandField 中的每個按鈕,產生具有 LinkButton (或 Button 或 ImageButton) 的 TemplateField ItemTemplate 。 這些按鈕 OnClientClick 屬性可以宣告方式指派,如我們使用 FormView 所見,或者可以使用下列模式以程序設計方式在適當的 DataBound 事件處理程式中存取:

Dim obj As ButtonType = CType(e.Row.FindControl("controlID"), ButtonType)

其中 controlID 是按鈕的 ID 屬性值。 雖然此模式仍然需要轉換的硬式編碼類型,但它不需要編製索引,讓版面配置得以變更,而不會造成運行時錯誤。

摘要

JavaScript confirm(string) 函式是控制表單提交工作流程的常用技術。 執行時,函式會顯示包含兩個按鈕的強制回應用戶端對話框:[確定] 和 [取消]。 如果使用者按下 [確定],函式會 confirm(string)true回 ;按兩下 [取消] 會傳 false回 。 如果提交程式期間事件處理程式傳回 false,這項功能與瀏覽器的行為一起取消表單提交,可用來在刪除記錄時顯示確認消息框。

confirm(string)式可以透過 control s OnClientClick 屬性與 Button Web 控件的用戶端onclick事件處理程式相關聯。 在範本中使用 [刪除] 按鈕時 - 在其中一個 FormView 範本或 DetailsView 或 GridView 的 TemplateField 中使用時, 這個屬性可以宣告方式或以程式設計方式設定,如本教學課程中所見。

快樂的程序設計!

關於作者

Scott Mitchell 是 1998 年以來,1998 年與 Microsoft Web 技術合作的 篇 ASP/ASP.NET 書籍和 4GuysFromRolla.com 作者。 Scott 是獨立的顧問、訓練者和作者。 他的最新書籍是 Sams 在 24 小時內自行 ASP.NET 2.0。 您可以透過mitchell@4GuysFromRolla.com部落格連到,也可以透過其部落格來存取,網址為 http://ScottOnWriting.NET