削除時、クライアント側の確認を追加する (VB)

作成者: Scott Mitchell

PDF のダウンロード

これまでに作成したインターフェイスでは、ユーザーが [編集] ボタンをクリックする目的で [削除] ボタンをクリックすると、誤ってデータを削除する可能性があります。 このチュートリアルでは、[削除] ボタンをクリックしたときに表示されるクライアント側の確認ダイアログ ボックスを追加します。

はじめに

過去のいくつかのチュートリアルでは、アプリケーション アーキテクチャ、ObjectDataSource、およびデータ Web コントロールを組み合わせ、挿入、編集、および削除機能を提供する方法について説明しました。 これまでに調べた削除インターフェイスは、クリックするとポストバックが発生し、ObjectDataSource の Delete() メソッドを呼び出す Delete ボタンで構成されています。 次に、 メソッドは Delete() 、ビジネス ロジック層から構成されたメソッドを呼び出します。これにより、呼び出しがデータ アクセス層に伝達され、実際 DELETE のステートメントがデータベースに発行されます。

このユーザー インターフェイスを使用すると、訪問者は GridView、DetailsView、または FormView コントロールを使用してレコードを削除することができますが、ユーザーが [削除] ボタンをクリックすると、何らかの確認は行いません。 ユーザーが [編集] をクリックしようとしたときに誤って [削除] ボタンをクリックした場合、更新する予定のレコードは削除されます。 これを防ぐために、このチュートリアルでは、[削除] ボタンをクリックしたときに表示されるクライアント側の確認ダイアログ ボックスを追加します。

JavaScript confirm(string) 関数は、文字列入力パラメーターをモーダル ダイアログ ボックス内のテキストとして表示します。このダイアログ ボックスには、[OK] と [キャンセル] の 2 つのボタンが用意されています (図 1 を参照)。 この関数は confirm(string) 、クリックされたボタン (trueユーザーが [OK] をクリックした場合、および false [キャンセル] をクリックした場合) に応じてブール値を返します。

JavaScript confirm(string) メソッドモーダル Client-Side メッセージ ボックスを表示します

図 1: JavaScript confirm(string) メソッドがモーダル メッセージ ボックス Client-Side 表示する

フォームの送信中に、 の false 値がクライアント側のイベント ハンドラーから返された場合、フォームの送信は取り消されます。 この機能を使用すると、Delete ボタンのクライアント側 onclick イベント ハンドラーから への呼び出しの値を返すことができます confirm("Are you sure you want to delete this product?")。 ユーザーが [キャンセル] をクリックすると、 confirm(string) false が返され、フォームの送信が取り消されます。 ポストバックがない場合、削除ボタンがクリックされた製品は削除されません。 ただし、ユーザーが確認ダイアログ ボックスで [OK] をクリックした場合、ポストバックは継続され、製品は削除されます。 この手法の詳細については、「 Using JavaScript s confirm() Method to Control Form Submission 」を参照してください。

必要なクライアント側スクリプトの追加は、CommandField を使用する場合よりもテンプレートを使用する場合と若干異なります。 したがって、このチュートリアルでは、FormView と GridView の両方の例を見ていきます。

注意

このチュートリアルで説明したように、クライアント側の確認手法を使用すると、ユーザーは JavaScript をサポートするブラウザーにアクセスしており、JavaScript が有効になっていることを前提としています。 これらの前提条件のいずれかが特定のユーザーに当てはまらない場合、[削除] ボタンをクリックすると、すぐにポストバックが発生します (確認メッセージ ボックスは表示されません)。

手順 1: 削除をサポートする FormView の作成

まず、フォルダー内EditInsertDeleteConfirmationOnDelete.aspxページに FormView を追加し、それを新しい ObjectDataSource にバインドし、クラスの GetProducts() メソッドを介して製品情報をProductsBLLプルバックします。 また、クラス s メソッドが ProductsBLL ObjectDataSource の DeleteProduct(productID) メソッドにマップされるように ObjectDataSource Delete() を構成します。INSERT タブと UPDATE タブのドロップダウン リストが (None) に設定されていることを確認します。 最後に、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 の OldValuesParameterFormatString プロパティを少しクリアしてください。

削除のみをサポートする ObjectDataSource コントロールにバインドされているため、FormView には ItemTemplate [削除] ボタンのみが表示され、[新規] ボタンと [更新] ボタンがありません。 ただし、FormView の宣言型マークアップには、削除できる余分な EditItemTemplateInsertItemTemplateが含まれています。 をカスタマイズ ItemTemplate して、製品データ フィールドのサブセットのみが表示されるようにします。 私は、そのサプライヤーとカテゴリ名の上の見出しに製品の名前を <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>

これらの変更により、ユーザーが製品を一度に 1 つずつ切り替え、単に [削除] ボタンをクリックするだけで製品を削除できる、完全に機能する Web ページが用意されています。 図 2 は、ブラウザーを介して表示した場合のこれまでの進行状況のスクリーン ショットを示しています。

FormView には、1 つの製品に関する情報が表示されます

図 2: FormView には、1 つの製品に関する情報が表示されます (クリックするとフルサイズの画像が表示されます)

手順 2: onclick イベント Client-Side 削除ボタンから confirm(string) 関数を呼び出す

FormView を作成したら、最後の手順では、訪問者がクリックしたときに JavaScript confirm(string) 関数が呼び出されるように [削除] ボタンを構成します。 Button、LinkButton、または ImageButton のクライアント側イベントにクライアント側 onclick スクリプトを追加するには、 を使用 OnClientClick propertyします。これは、ASP.NET 2.0 の新機能です。 関数の値を返す必要があるため、このプロパティを 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 は、この確認の動作中のスクリーン ショットを示しています。 [削除] ボタンをクリックすると、確認ダイアログ ボックスが表示されます。 ユーザーが [キャンセル] をクリックすると、ポストバックは取り消され、製品は削除されません。 ただし、ユーザーが [OK] をクリックすると、ポストバックが続行され、ObjectDataSource の Delete() メソッドが呼び出され、削除されるデータベース レコードに結び付きます。

注意

JavaScript 関数に confirm(string) 渡される文字列は、(引用符ではなく) アポストロフィで区切られます。 JavaScript では、文字列はどちらかの文字を使用して区切ることができます。 ここではアポストロフィを使用して、渡される文字列の区切り記号でプロパティ値に confirm(string) 使用される OnClientClick 区切り記号とのあいまいさが生じないようにします。

[削除] ボタンをクリックしたときに確認が表示されるようになりました

図 3: 削除ボタンをクリックすると確認が表示されるようになりました (クリックするとフルサイズの画像が表示されます)

手順 3: CommandField で削除ボタンの OnClientClick プロパティを構成する

テンプレートで Button、LinkButton、または ImageButton を直接操作する場合は、JavaScript confirm(string) 関数の結果を返すようにプロパティをOnClientClick構成するだけで、確認ダイアログ ボックスを関連付けることができます。 ただし、GridView または DetailsView に [削除] ボタンのフィールドを追加する CommandField には OnClientClick 、宣言によって設定できるプロパティはありません。 代わりに、プログラムで GridView または DetailsView の適切な DataBound イベント ハンドラーの [削除] ボタンを参照し、そのプロパティを OnClientClick そこに設定する必要があります。

注意

適切なDataBoundイベント ハンドラーで Delete ボタンの プロパティOnClientClickを設定すると、現在のレコードにバインドされたデータにアクセスできます。 つまり、確認メッセージを拡張して、特定のレコードに関する詳細を含めることができます。たとえば、"Chai 製品を削除しますか?このようなカスタマイズは、データ バインド構文を使用するテンプレートでも可能です。

CommandField の OnClientClick [削除] ボタンのプロパティの設定を練習するには、ページに GridView を追加します。 FormView で使用されるのと同じ ObjectDataSource コントロールを使用するように、この GridView を構成します。 また、GridView の BoundFields には、製品の名前、カテゴリ、および仕入先のみを含むように制限します。 最後に、GridView のスマート タグから [削除を有効にする] チェック ボックスをチェックします。 これにより、プロパティが に設定された CommandField が GridView の Columns コレクション ShowDeleteButtontrue追加されます。

これらの変更を行った後、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 を ButtonType property使用してカスタマイズできます。 commandFieldIndex は GridView コレクション内の CommandField の序数インデックスですが、controlIndex は CommandField コレクションColumns内の Delete ボタンのControlsインデックスです。 controlIndex 値は、CommandField 内の他のボタンに対するボタンの位置によって異なります。 たとえば、CommandField に表示される唯一のボタンが [削除] ボタンの場合は、インデックス 0 を使用します。 ただし、[削除] ボタンの前に [編集] ボタンがある場合は、インデックス 2 を使用します。 インデックス 2 が使用される理由は、[削除] ボタンの前に CommandField によって 2 つのコントロールが追加されるためです。[編集] ボタンと [編集] ボタンと [削除] ボタンの間にスペースを追加するために使用される LiteralControl です。

この特定の例では、CommandField は LinkButtons を使用し、左端のフィールドの commandFieldIndex は 0 です。 CommandField に [削除] ボタン以外のボタンがないため、 controlIndex は 0 を使用します。

CommandField の [削除] ボタンを参照した後、次に現在の GridView 行にバインドされている製品に関する情報を取得します。 最後に、Delete ボタンの OnClientClick プロパティを、製品の名前を含む適切な JavaScript に設定します。 関数に confirm(string) 渡される JavaScript 文字列はアポストロフィを使用して区切られますので、製品名内に出現するすべてのアポストロフィをエスケープする必要があります。 特に、製品名に含まれるアポストロフィは、"\'" でエスケープされます。

これらの変更が完了すると、GridView の [削除] ボタンをクリックすると、カスタマイズされた確認ダイアログ ボックスが表示されます (図 4 を参照)。 FormView の確認メッセージ ボックスと同様に、ユーザーが [キャンセル] をクリックするとポストバックが取り消され、削除が行われなくなります。

注意

この手法を使用して、DetailsView の CommandField の [削除] ボタンにプログラムでアクセスすることもできます。 ただし、DetailsView の場合は、DetailsView にイベントがないため、イベントのイベント ハンドラー DataBoundRowDataBound 作成します。

GridView の [削除] ボタンをクリックすると、カスタマイズされた確認ダイアログ ボックスが表示されます

図 4: GridView の [削除] ボタンをクリックすると、[カスタマイズされた確認] ダイアログ ボックスが表示されます (フルサイズの画像を表示する 場合はクリックします)

TemplateFields の使用

CommandField の欠点の 1 つは、そのボタンにインデックスを作成してアクセスし、結果のオブジェクトを適切なボタンの種類 (Button、LinkButton、または ImageButton) にキャストする必要があることです。 "マジック番号" とハードコーディングされた型を使用すると、ランタイムまで検出できない問題が招待されます。 たとえば、ユーザーまたは別の開発者が、将来のどこかの時点で CommandField に新しいボタンを追加したり ([編集] ボタンなど)、プロパティを変更 ButtonType したりした場合でも、既存のコードはエラーなしでコンパイルされますが、ページにアクセスすると、コードの書き方や変更内容によっては、例外や予期しない動作が発生する可能性があります。

別の方法として、GridView と DetailsView の CommandFields を TemplateFields に変換します。 これにより、CommandField 内の各ボタンの LinkButton (または Button または ImageButton) を持つ ItemTemplate TemplateField が生成されます。 これらのボタン の OnClientClick プロパティは、FormView で見たとおり、宣言によって割り当てることができます。または、次のパターンを使用して、適切な DataBound イベント ハンドラーでプログラムでアクセスできます。

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

ここで、controlID はボタンの ID プロパティの値です。 このパターンではキャストにハードコーディングされた型が必要ですが、インデックス作成が不要になり、実行時エラーが発生することなくレイアウトを変更できます。

まとめ

JavaScript confirm(string) 関数は、フォーム送信ワークフローを制御するために一般的に使用される手法です。 関数を実行すると、2 つのボタン [OK] と [キャンセル] を含むモーダルのクライアント側ダイアログ ボックスが表示されます。 ユーザーが [OK] をクリックすると、関数は confirm(string) を返 trueします。[キャンセル] をクリックすると が返されます false。 この機能は、送信プロセス中にイベント ハンドラーが を返 falseした場合にフォームの送信を取り消すブラウザーの動作と組み合わせて、レコードを削除するときに確認メッセージ ボックスを表示するために使用できます。

関数は confirm(string) 、コントロールの プロパティを使用して、Button Web コントロールのクライアント側 onclick イベント ハンドラーに OnClientClick 関連付けることができます。 テンプレート内の [削除] ボタン (FormView のテンプレートの 1 つ、または DetailsView または GridView の TemplateField) を使用する場合、このプロパティは、このチュートリアルで説明したように、宣言またはプログラムによって設定できます。

プログラミングに満足!

著者について

7 冊の ASP/ASP.NET 書籍の著者であり、 4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジと協力しています。 Scott は、独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズは24時間で2.0 ASP.NET 自分自身を教えています。 にアクセスするか、ブログを使用して にアクセスmitchell@4GuysFromRolla.comできます。これは でhttp://ScottOnWriting.NET見つけることができます。