挿入、更新、削除に関連付けられているイベントを調べる (VB)

作成者: Scott Mitchell

PDF のダウンロード

このチュートリアルでは、ASP.NET データ Web コントロールの挿入、更新、または削除操作の前後に発生するイベントの使用について説明します。 また、製品フィールドのサブセットのみを更新するように編集インターフェイスをカスタマイズする方法についても説明します。

はじめに

GridView、DetailsView、または FormView コントロールの組み込みの挿入、編集、または削除機能を使用する場合、エンド ユーザーが新しいレコードの追加または既存のレコードの更新または削除のプロセスを完了すると、さまざまな手順が発生します。 前のチュートリアルで説明したように、GridView で行を編集すると、[編集] ボタンが [更新] ボタンと [キャンセル] ボタンに置き換えられ、BoundFields がテキスト ボックスに変わります。 エンド ユーザーがデータを更新して [更新] をクリックすると、ポストバック時に次の手順が実行されます。

  1. GridView は、編集されたレコードの UpdateParameters 一意の識別フィールド (プロパティを使用 DataKeyNames ) と、ユーザーが入力した値を ObjectDataSource に設定します
  2. GridView は ObjectDataSource の Update() メソッドを呼び出し、基になるオブジェクトの適切なメソッドを呼び出します (ProductsDAL.UpdateProduct前のチュートリアルでは)
  3. 基になるデータ (更新された変更が含まれる) は、GridView に再バインドされます

この一連の手順では、多数のイベントが発生し、必要に応じてカスタム ロジックを追加するイベント ハンドラーを作成できます。 たとえば、手順 1 より前では、GridView の RowUpdating イベントが発生します。 検証エラーが発生した場合は、この時点で更新要求を取り消すことができます。 メソッドが Update() 呼び出されると、ObjectDataSource の Updating イベントが発生し、 のいずれかの値を追加またはカスタマイズする機会が提供されます UpdateParameters。 ObjectDataSource の基になるオブジェクトのメソッドの実行が完了すると、ObjectDataSource の Updated イベントが発生します。 イベントの Updated イベント ハンドラーは、影響を受けた行の数や例外が発生したかどうかなど、更新操作に関する詳細を調べることができます。 最後に、手順 2 の後に GridView の RowUpdated イベントが発生します。このイベントのイベント ハンドラーは、先ほど実行した更新操作に関する追加情報を調べることができます。

図 1 は、GridView を更新するときのこの一連のイベントと手順を示しています。 図 1 のイベント パターンは、GridView を使用した更新とは一意ではありません。 GridView、DetailsView、または FormView からデータを挿入、更新、または削除すると、データ Web コントロールと ObjectDataSource の両方に対して、同じ一連のプリレベル イベントとポストレベル イベントが生成されます。

GridView でデータを更新するときに発生する一連の事前イベントと事後イベント

図 1: GridView でデータを更新するときに発生する一連の事前イベントと事後イベント (フルサイズの画像を表示する をクリックします)

このチュートリアルでは、これらのイベントを使用して、ASP.NET データ Web コントロールの組み込みの挿入、更新、および削除機能を拡張する方法について説明します。 また、製品フィールドのサブセットのみを更新するように編集インターフェイスをカスタマイズする方法についても説明します。

手順 1: 製品とUnitPriceフィールドをProductName更新する

前のチュートリアルの編集インターフェイスでは、読み取り専用ではない すべての 製品フィールドを含める必要がありました。 データを更新するときに、GridView QuantityPerUnit からフィールドを削除した場合、データ Web コントロールは ObjectDataSource の QuantityPerUnitUpdateParameters 値を設定しません。 その後、ObjectDataSource は の値 Nothing をビジネス ロジック レイヤー (BLL) メソッドに UpdateProduct 渡します。これにより、編集されたデータベース レコードの QuantityPerUnit 列が値に NULL 変更されます。 同様に、 などの ProductName必須フィールドが編集インターフェイスから削除されると、"Column 'ProductName' does not allow nulls" 例外で更新は失敗します。 この動作の理由は、ObjectDataSource がクラスのUpdateProductメソッドをProductsBLL呼び出すように構成されており、各製品フィールドの入力パラメーターが必要だったためです。 したがって、ObjectDataSource の UpdateParameters コレクションには、各メソッドの入力パラメーターのパラメーターが含まれていました。

エンド ユーザーがフィールドのサブセットのみを更新できるようにするデータ Web コントロールを提供する場合は、ObjectDataSource Updating のイベント ハンドラーで欠損UpdateParameters値をプログラムで設定するか、フィールドのサブセットのみを必要とする BLL メソッドを作成して呼び出す必要があります。 この後者のアプローチを見てみましょう。

具体的には、編集可能な GridView の フィールドと UnitPrice フィールドのみをProductName表示するページを作成しましょう。 この GridView の編集インターフェイスでは、ユーザーが 2 つの表示フィールド ProductNameUnitPriceのみを更新できます。 この編集インターフェイスは製品のフィールドのサブセットのみを提供するため、既存の BLL UpdateProduct のメソッドを使用し、不足している製品フィールド値をイベント ハンドラーでプログラムによって Updating 設定する ObjectDataSource を作成するか、GridView で定義されているフィールドのサブセットのみを必要とする新しい BLL メソッドを作成する必要があります。 このチュートリアルでは、後者のオプションを使用し、 メソッドのUpdateProductオーバーロードを作成します。1 つは、、unitPrice、および productIDの 3 つの入力パラメーターproductNameのみを受け取ります。

<System.ComponentModel.DataObjectMethodAttribute _
    (System.ComponentModel.DataObjectMethodType.Update, False)> _
    Public Function UpdateProduct(productName As String, _
        unitPrice As Nullable(Of Decimal), productID As Integer) _
        As Boolean

    Dim products As Northwind.ProductsDataTable = _
        Adapter.GetProductByProductID(productID)

    If products.Count = 0 Then
        Return False
    End If

    Dim product As Northwind.ProductsRow = products(0)

    product.ProductName = productName
    If Not unitPrice.HasValue Then
        product.SetUnitPriceNull()
    Else
        product.UnitPrice = unitPrice.Value
    End If

    Dim rowsAffected As Integer = Adapter.Update(product)

    Return rowsAffected = 1
End Function

UpdateProduct のメソッドと同様に、このオーバーロードは、指定された ProductIDを持つ製品がデータベースに存在するかどうかを確認することから始まります。 そうでない場合は、製品情報の False更新要求が失敗したことを示す が返されます。 それ以外の場合は、既存の製品レコードとProductNameUnitPriceフィールドを適宜更新し、TableAdapter の Update() メソッドを呼び出してインスタンスを渡して更新をProductsRowコミットします。

このクラスに ProductsBLL 加えて、簡略化された GridView インターフェイスを作成する準備ができました。 フォルダー内の をDataModificationEvents.aspxEditInsertDelete開き、ページに GridView を追加します。 新しい ObjectDataSource を作成し、 へのメソッド マッピングGetProductsSelect()、および Update() 入力パラメーターのみを受け取るオーバーロードへのUpdateProductメソッド マッピングで クラスをproductNameunitPriceproductID使用ProductsBLLするように構成します。 図 2 は、ObjectDataSource のメソッドをクラスのUpdate()新しいUpdateProductメソッド オーバーロードにProductsBLLマッピングするときのデータ ソースの作成ウィザードを示しています。

ObjectDataSource の Update() メソッドを新しい UpdateProduct オーバーロードにマップする

図 2: ObjectDataSource の Update() メソッドを新しい UpdateProduct オーバーロードにマップする (クリックするとフルサイズの画像が表示されます)

この例では、最初はデータを編集する必要がありますが、レコードを挿入または削除する機能は必要ないため、ObjectDataSource Insert() の メソッドとメソッドを INSERT タブと Delete() DELETE タブに移動し、ドロップダウン リストから (None) を選択して、クラスの ProductsBLL メソッドにマップしないことを明示的に示してください。

[挿入] タブと [削除] タブの Drop-Down リストから [(なし)] を選択します

図 3: INSERT タブと DELETE タブの Drop-Down リストから [(なし)] を選択します (フルサイズの画像を表示するには、ここをクリックします)

このウィザードを完了したら、GridView のスマート タグから [編集を有効にする] チェック ボックスをチェックします。

データ ソースの作成ウィザードを完了し、GridView にバインドすると、Visual Studio は両方のコントロールの宣言構文を作成しました。 [ソース] ビューに移動して、ObjectDataSource の宣言型マークアップを調べます。次に示します。

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    OldValuesParameterFormatString="original_{0}" SelectMethod="GetProducts"
    TypeName="ProductsBLL" UpdateMethod="UpdateProduct">
    <UpdateParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <asp:Parameter Name="productID" Type="Int32" />
    </UpdateParameters>
</asp:ObjectDataSource>

ObjectDataSource の メソッドと メソッドにはInsert()マッピングがないため、セクションまたは DeleteParameters セクションはありませんInsertParametersDelete() さらに、 メソッドは 3 つの入力パラメーターのみを受け取るメソッド オーバーロードにUpdateProductマップされるためUpdate()UpdateParametersセクションには 3 つのParameterインスタンスしかありません。

ObjectDataSource OldValuesParameterFormatString の プロパティが に設定されていることに注意してください original_{0}。 このプロパティは、データ ソースの構成ウィザードを使用すると、Visual Studio によって自動的に設定されます。 ただし、BLL メソッドでは元 ProductID の値が渡されることを想定していないため、ObjectDataSource の宣言構文からこのプロパティの割り当てを完全に削除してください。

注意

デザイン ビューのOldValuesParameterFormatStringプロパティ ウィンドウからプロパティ値をクリアするだけで、宣言構文にはプロパティが存在しますが、空の文字列に設定されます。 宣言構文からプロパティを完全に削除するか、プロパティ ウィンドウから値を既定値{0}に設定します。

ObjectDataSource は製品の名前、価格、ID のみを持 UpdateParameters ちますが、Visual Studio では各製品のフィールドに対して GridView に BoundField または CheckBoxField が追加されています。

GridView には、製品の各フィールドの BoundField または CheckBoxField が含まれています

図 4: GridView には、製品の各フィールドの BoundField または CheckBoxField が含まれています (フルサイズの画像を表示する をクリックします)。

エンド ユーザーが製品を編集し、その [更新] ボタンをクリックすると、GridView によって読み取り専用ではないフィールドが列挙されます。 次に、ObjectDataSource のコレクション内の対応するパラメーターの UpdateParameters 値を、ユーザーが入力した値に設定します。 対応するパラメーターがない場合、GridView によってコレクションに追加されます。 したがって、GridView に製品のすべてのフィールドの BoundFields と CheckBoxFields が含まれている場合、ObjectDataSource は、ObjectDataSource の宣言型マークアップが 3 つの入力パラメーターのみを指定しているにもかかわらず、これらのパラメーターをすべて受け取るオーバーロードを呼び出 UpdateProduct します (図 5 を参照)。 同様に、GridView に、オーバーロードの入力パラメーター UpdateProduct に対応しない読み取り専用でない製品フィールドの組み合わせがある場合は、更新しようとすると例外が発生します。

GridView は、ObjectDataSource の UpdateParameters コレクションにパラメーターを追加します

図 5: GridView は ObjectDataSource のコレクションにパラメーターを追加します (フルサイズのUpdateParameters画像を表示する をクリックします)

ObjectDataSource が、製品の名前、価格、ID のみを受け取るオーバーロードを呼び出UpdateProductすようにするには、 と UnitPriceの編集可能なフィールドを ProductName GridView に制限する必要があります。 これを行うには、他の BoundFields と CheckBoxFields を削除するか、他のフィールドの ReadOnly プロパティを に True設定するか、2 つの組み合わせを使用します。 このチュートリアルでは、 と UnitPrice BoundFields を除くすべての GridView フィールドをProductName削除します。その後、GridView の宣言型マークアップは次のようになります。

<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
    <Columns>
        <asp:CommandField ShowEditButton="True" />
        <asp:BoundField DataField="ProductName"
          HeaderText="ProductName" SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
          SortExpression="UnitPrice" />
    </Columns>
</asp:GridView>

オーバーロードでは UpdateProduct 3 つの入力パラメーターが必要ですが、GridView には BoundFields が 2 つだけあります。 これは、入力パラメーターが主キー値であり、編集された行の プロパティの値をDataKeyNames介して渡されるためproductIDです。

GridView とオーバーロードを UpdateProduct 使用すると、ユーザーは他の製品フィールドを失うことなく、製品の名前と価格のみを編集できます。

インターフェイスはプロダクトの名前および価格だけを編集することを可能にする

図 6: インターフェイスでは、製品の名前と価格のみを編集できます (フルサイズの画像を表示する をクリックします)。

注意

前のチュートリアルで説明したように、GridView のビューステートを有効にすることが非常に重要です (既定の動作)。 GridView の EnableViewState プロパティを に false設定すると、同時実行ユーザーが意図せずにレコードを削除または編集するリスクが発生します。

書式設定のUnitPrice改善

図 6 に示す GridView の例は機能しますが、 UnitPrice フィールドはまったく書式設定されていないため、通貨記号がなく小数点以下 4 桁の価格表示になります。 編集できない行に通貨書式を適用するには、BoundField DataFormatString の プロパティを UnitPrice{0:c}設定し、そのHtmlEncodeプロパティを にFalse設定します。

それに応じて、UnitPrice の DataFormatString プロパティと HtmlEncode プロパティを設定します

図 7: に応じて の プロパティと HtmlEncode プロパティをDataFormatString設定UnitPriceします (クリックするとフルサイズの画像が表示されます)

この変更により、編集可能でない行は価格を通貨として書式設定します。ただし、編集された行には、通貨記号がなく、小数点以下 4 桁の値が表示されます。

編集できない行が通貨値として書式設定されるようになりました

図 8: 編集できない行が通貨値として書式設定されるようになりました (フルサイズの画像を表示する をクリックします)

プロパティで DataFormatString 指定された書式設定手順は、BoundField ApplyFormatInEditMode の プロパティ True を に設定することで編集インターフェイスに適用できます (既定値は Falseです)。 このプロパティ Trueを に設定します。

UnitPrice BoundField の ApplyFormatInEditMode プロパティを True に設定します

図 9: BoundField ApplyFormatInEditMode の プロパティを にTrue設定UnitPriceします (クリックするとフルサイズの画像が表示されます)

この変更により、編集された行に表示される の値 UnitPrice も通貨として書式設定されます。

通貨として書式設定された編集済みの行の UnitPrice 値を示す GridView のスクリーンショット。

図 10: 編集された行の UnitPrice 値が通貨として書式設定されるようになりました (フルサイズの画像を表示する をクリックします)

ただし、$19.00 などのテキスト ボックスに通貨記号を使用して製品を更新すると、 が FormatExceptionスローされます。 GridView がユーザー指定の値を ObjectDataSource のUpdateParametersコレクションに割り当てようとすると、文字列 "$19.00" を Decimal パラメーターで必要な に変換UnitPriceできません (図 11 を参照)。 これを解決するために、GridView RowUpdating のイベントのイベント ハンドラーを作成し、通貨形式Decimalの としてユーザー指定UnitPriceを解析させることができます。

GridView のイベントは、2 番目のRowUpdatingパラメーターとして GridViewUpdateEventArgs 型のオブジェクトを受け取ります。これには、ObjectDataSource UpdateParameters のコレクションに割り当てる準備ができているユーザー指定の値を保持するプロパティの 1 つとしてディクショナリが含まれますNewValues。 イベント ハンドラー内の次のNewValuesコード行で通貨形式を使用して解析された 10 進値でコレクション内の既存UnitPriceの値をRowUpdating上書きできます。

Protected Sub GridView1_RowUpdating(sender As Object, e As GridViewUpdateEventArgs) _
    Handles GridView1.RowUpdating
    If e.NewValues("UnitPrice") IsNot Nothing Then
        e.NewValues("UnitPrice") = _
            Decimal.Parse(e.NewValues("UnitPrice").ToString(), _
                System.Globalization.NumberStyles.Currency)
    End If
End Sub

ユーザーが値 ("$19.00" など) を指定した UnitPrice 場合、この値は Decimal.Parse によって計算された 10 進値で上書きされ、値が通貨として解析されます。 これにより、通貨記号、コンマ、小数点などが発生した場合に小数点が正しく解析され、System.Globalization 名前空間の NumberStyles 列挙が使用されます。

図 11 は、ユーザーが指定した UnitPriceの通貨記号によって引き起こされる問題と、GridView の RowUpdating イベント ハンドラーを使用してこのような入力を正しく解析する方法の両方を示しています。

ObjectDataSource が UnitPrice フィールドを処理する方法と、GridView の RowUpdate イベント ハンドラーが文字列を 10 進数に変換する方法を示す図。

図 11: 編集された行の UnitPrice 値が通貨として書式設定されるようになりました (フルサイズの画像を表示する をクリックします)

手順 2: 禁止NULL UnitPrices

テーブルの列の値を許可 NULL するようにデータベースが Products 構成されている間、この特定の UnitPrice ページにアクセスするユーザーが値を NULLUnitPrice 指定できないようにすることができます。 つまり、ユーザーが製品行の編集時に値を入力 UnitPrice できない場合は、結果をデータベースに保存するのではなく、このページを通じて、編集された製品に価格が指定されている必要があることをユーザーに通知するメッセージを表示します。

GridViewUpdateEventArgs GridView RowUpdating のイベント ハンドラーに渡される オブジェクトには、 にTrue設定されている場合に更新プロセスを終了するプロパティが含まれていますCancel。 イベント ハンドラーを RowUpdating に設定Truee.Cancelするように拡張し、コレクション内の値に の値がある場合UnitPriceの理由を説明するメッセージをNewValuesNothing表示してみましょう。

まず、 という名前 MustProvideUnitPriceMessageのページに Label Web コントロールを追加します。 製品の更新時にユーザーが値の指定に失敗した場合、 UnitPrice このラベル コントロールが表示されます。 Label の プロパティを "製品のText価格を指定する必要があります" に設定します。また、次の定義を使用して、 という名前WarningStyles.css新しい CSS クラスを作成しました。

.Warning
{
    color: Red;
    font-style: italic;
    font-weight: bold;
    font-size: x-large;
}

最後に、Label CssClass の プロパティを に設定します Warning。 この時点で、Designerは、図 12 に示すように、GridView の上に赤、太字、斜体、特大のフォント サイズで警告メッセージを表示する必要があります。

GridView の上にラベルが追加されました

図 12: GridView の上にラベルが追加されました (フルサイズの画像を表示するをクリックします)

既定では、この Label は非表示にする必要があるため、イベント ハンドラーでそのプロパティを Page_LoadFalse設定Visibleします。

Protected Sub Page_Load(sender As Object, e As System.EventArgs) Handles Me.Load
    MustProvideUnitPriceMessage.Visible = False
End Sub

ユーザーが を指定 UnitPriceせずに製品を更新しようとすると、更新を取り消して警告ラベルを表示します。 GridView のイベント ハンドラーを RowUpdating 次のように拡張します。

Protected Sub GridView1_RowUpdating(sender As Object, e As GridViewUpdateEventArgs) _
    Handles GridView1.RowUpdating

    If e.NewValues("UnitPrice") IsNot Nothing Then
        e.NewValues("UnitPrice") = _
            Decimal.Parse(e.NewValues("UnitPrice").ToString(), _
                System.Globalization.NumberStyles.Currency)
    Else
        MustProvideUnitPriceMessage.Visible = True

        e.Cancel = True
    End If
End Sub

ユーザーが価格を指定せずに製品を保存しようとすると、更新が取り消され、役に立つメッセージが表示されます。 データベース (およびビジネス ロジック) では が許可 NULLUnitPrice されますが、この特定の ASP.NET ページでは許可されません。

ユーザーが UnitPrice を空白のままにすることはできません

図 13: ユーザーを空白のままに UnitPrice することはできません (フルサイズの画像を表示する場合はクリックします)

ここまでは、GridView の イベントを使用して、ObjectDataSource UpdateParametersRowUpdatingコレクションに割り当てられているパラメーター値をプログラムで変更する方法と、更新プロセスを完全に取り消す方法について説明しました。 これらの概念は DetailsView コントロールと FormView コントロールに引き継がれ、挿入と削除にも適用されます。

これらのタスクは、ObjectDataSource レベルで、そのInsertingUpdatingイベント、、および Deleting イベントのイベント ハンドラーを使用して実行することもできます。 これらのイベントは、基になるオブジェクトの関連付けられたメソッドが呼び出される前に発生し、入力パラメーター コレクションを変更したり、操作を完全に取り消したりする最後の機会を提供します。 これら 3 つのイベントのイベント ハンドラーには、次の 2 つのプロパティを持つ ObjectDataSourceMethodEventArgs 型のオブジェクトが渡されます。

  • Cancel (に設定されている場合) は True、実行されている操作を取り消します
  • InputParameters。イベント ハンドラーが 、、または イベント用かどうかに応じて、Updatingまたは DeletingDeleteParametersのコレクションInsertParametersUpdateParametersですInserting

ObjectDataSource レベルでパラメーター値を操作する方法を説明するために、ユーザーが新しい製品を追加できるようにする DetailsView をページに含めましょう。 この DetailsView は、新しい製品をデータベースにすばやく追加するためのインターフェイスを提供するために使用されます。 新しい製品を追加するときに一貫したユーザー インターフェイスを維持するために、 フィールドと UnitPrice フィールドの値ProductNameのみを入力できるようにしましょう。 既定では、DetailsView の挿入インターフェイスで指定されていない値は、データベース値に NULL 設定されます。 ただし、ObjectDataSource の Inserting イベントを使用して、間もなく表示されるように、さまざまな既定値を挿入できます。

手順 3: 新しい製品を追加するためのインターフェイスを提供する

ツールボックスから GridView の上のDesignerに DetailsView をドラッグし、そのプロパティと Width プロパティをHeightクリアして、ページ上に既に存在する ObjectDataSource にバインドします。 これにより、製品の各フィールドに BoundField または CheckBoxField が追加されます。 この DetailsView を使用して新しい製品を追加するため、スマート タグから [挿入を有効にする] オプションをチェックする必要があります。ただし、ObjectDataSource のメソッドが クラスのInsert()ProductsBLLメソッドにマップされていないため、このようなオプションはありません (データ ソースを構成するときに、このマッピングを (None) に設定したことを思い出してください(図 3 を参照)。

ObjectDataSource を構成するには、スマート タグから [データ ソースの構成] リンクを選択し、ウィザードを起動します。 最初の画面では、ObjectDataSource がバインドされている基になるオブジェクトを変更できます。は に設定したままに ProductsBLLしておきます。 次の画面では、ObjectDataSource のメソッドから基になるオブジェクトへのマッピングが一覧表示されます。 メソッドと Delete() メソッドをどのメソッドにもマップしないことを明示的に示しましたがInsert()、[INSERT] タブと [DELETE] タブに移動すると、マッピングが存在することがわかります。 これは、 ProductsBLLAddProduct メソッドと DeleteProduct メソッドが 属性をDataObjectMethodAttribute使用して、 と Delete()の既定のメソッドInsert()であることを示しているためです。 そのため、ObjectDataSource ウィザードは、他の値が明示的に指定されていない限り、ウィザードを実行するたびにこれらを選択します。

メソッドは Insert() メソッドを指したまま AddProduct にしますが、DELETE タブのドロップダウン リストを (None) に設定します。

INSERT タブの Drop-Down リストを AddProduct メソッドに設定する

図 14: INSERT タブの Drop-Down リストを メソッドに AddProduct 設定します (フルサイズの画像を表示する 場合は クリックします)

[DELETE] タブの [Drop-Down リスト] を [(なし)] に設定します

図 15: DELETE タブの Drop-Down リストを (なし) に設定します (フルサイズの画像を表示するにはクリックします)

これらの変更を行うと、次に示すように、ObjectDataSource の宣言構文が展開され、コレクションが InsertParameters 含まれます。

<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    SelectMethod="GetProducts" TypeName="ProductsBLL"
    UpdateMethod="UpdateProduct" OnUpdating="ObjectDataSource1_Updating"
    InsertMethod="AddProduct" OldValuesParameterFormatString="original_{0}">
    <UpdateParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <asp:Parameter Name="productID" Type="Int32" />
    </UpdateParameters>
    <InsertParameters>
        <asp:Parameter Name="productName" Type="String" />
        <asp:Parameter Name="supplierID" Type="Int32" />
        <asp:Parameter Name="categoryID" Type="Int32" />
        <asp:Parameter Name="quantityPerUnit" Type="String" />
        <asp:Parameter Name="unitPrice" Type="Decimal" />
        <asp:Parameter Name="unitsInStock" Type="Int16" />
        <asp:Parameter Name="unitsOnOrder" Type="Int16" />
        <asp:Parameter Name="reorderLevel" Type="Int16" />
        <asp:Parameter Name="discontinued" Type="Boolean" />
    </InsertParameters>
</asp:ObjectDataSource>

ウィザードを再実行すると、 プロパティが追加されました OldValuesParameterFormatString 。 このプロパティを既定値 ({0}) に設定するか、宣言構文から完全に削除して、このプロパティをクリアします。

挿入機能を提供する ObjectDataSource では、DetailsView のスマート タグに [挿入を有効にする] チェック ボックスが含まれるようになりました。をDesignerに戻り、このオプションをチェックします。 次に、DetailsView を減らして、BoundFields ProductNameUnitPrice と - と CommandField が 2 つだけになるようにします。 この時点で、DetailsView の宣言構文は次のようになります。

<asp:DetailsView ID="DetailsView1" runat="server" AutoGenerateRows="False"
    DataKeyNames="ProductID" DataSourceID="ObjectDataSource1">
    <Fields>
        <asp:BoundField DataField="ProductName"
          HeaderText="ProductName" SortExpression="ProductName" />
        <asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
          SortExpression="UnitPrice" />
        <asp:CommandField ShowInsertButton="True" />
    </Fields>
</asp:DetailsView>

図 16 は、この時点でブラウザーを介して表示された場合のこのページを示しています。 ご覧のように、DetailsView には最初の製品 (Chai) の名前と価格が一覧表示されます。 ただし、必要なのは、ユーザーが新しい製品をデータベースにすばやく追加するための手段を提供する挿入インターフェイスです。

DetailsView は現在、Read-Only モードでレンダリングされています

図 16: DetailsView は現在、Read-Only モードでレンダリングされています (フルサイズの画像を表示するには、ここをクリックします)

DetailsView を挿入モードで表示するには、 プロパティを に設定 DefaultMode する Inserting必要があります。 これにより、最初にアクセスしたときに DetailsView が挿入モードでレンダリングされ、新しいレコードを挿入した後も保持されます。 図 17 に示すように、このような DetailsView には、新しいレコードを追加するためのクイック インターフェイスが用意されています。

DetailsView は、新しい製品を迅速に追加するためのインターフェイスを提供します

図 17: DetailsView は、新しい製品を迅速に追加するためのインターフェイスを提供します (フルサイズの画像を表示する をクリックします)

ユーザーが製品名と価格 (図 17 のように "Acme Water" や 1.99 など) を入力して [挿入] をクリックすると、ポストバックが続き、挿入ワークフローが開始され、新しい製品レコードがデータベースに追加されます。 DetailsView は挿入インターフェイスを維持し、図 18 に示すように、GridView は新しい製品を含めるためにデータ ソースに自動的にリバウンドされます。

製品

図 18: 製品 "アクメ ウォーター" がデータベースに追加されました

図 18 の GridView には表示されませんが、DetailsView インターフェイス CategoryIDSupplierIDQuantityPerUnitなどから欠落している製品フィールドには、データベース値が割り当てられますNULL。 これは、次の手順を実行して確認できます。

  1. Visual Studio のサーバー エクスプローラーに移動する
  2. データベース ノードの NORTHWND.MDF 展開
  3. データベース テーブル ノードを Products 右クリックします
  4. [テーブル データの表示] を選択します

これにより、テーブル内 Products のすべてのレコードが一覧表示されます。 図 19 に示すように、、、 以外ProductIDProductNameUnitPriceのすべての新製品の列には値があります。NULL

DetailsView に指定されていない製品フィールドには NULL 値が割り当てられます

図 19: DetailsView に指定されていない製品フィールドは割り当てられた NULL 値です (フルサイズの画像を表示する 場合はクリックします)

これらの列値の 1 つ以上に対して 以外 NULL の既定値を指定することをお勧めします。これは、 が最適な既定のオプションではないか、 NULL データベース列自体で が許可 NULL されていないためです。 これを実現するために、DetailsView InputParameters のコレクションのパラメーターの値をプログラムで設定できます。 この割り当ては、DetailsView ItemInserting のイベントのイベント ハンドラーまたは ObjectDataSource の Inserting イベントのいずれかで実行できます。 データ Web コントロール レベルでの事前および事後レベルのイベントの使用を既に見てきたので、今回は ObjectDataSource のイベントを使用して調べてみましょう。

手順 4: パラメーターとSupplierIDパラメーターに値をCategoryID割り当てる

このチュートリアルでは、このインターフェイスを介して新しい製品を追加するときに、 と SupplierID の値を 1 にCategoryID割り当てる必要があるとします。 前述のように、ObjectDataSource には、データ変更プロセス中に発生する事前および事後レベルのイベントのペアがあります。 その Insert() メソッドが呼び出されると、ObjectDataSource は最初にそのイベントを Inserting 発生させ、次にその Insert() メソッドがマップされているメソッドを呼び出し、最後に イベントを Inserted 発生させます。 イベント ハンドラーは Inserting 、入力パラメーターを調整したり、操作を完全にキャンセルしたりする最後の機会を提供します。

注意

実際のアプリケーションでは、ユーザーがカテゴリとサプライヤーを指定できるようにするか、または(盲目的に ID 1 を選択するのではなく) 何らかの条件またはビジネス ロジックに基づいてこの値を選択する必要があります。 この例では、ObjectDataSource の事前レベル イベントから入力パラメーターの値をプログラムで設定する方法を示しています。

ObjectDataSource Inserting のイベントのイベント ハンドラーを作成します。 イベント ハンドラーの 2 番目の入力パラメーターは 型ObjectDataSourceMethodEventArgsのオブジェクトであり、パラメーター コレクション () にアクセスするプロパティと、操作を取り消すプロパティ (InputParametersCancel) を持っています。

Protected Sub ObjectDataSource1_Inserting _
    (sender As Object, e As ObjectDataSourceMethodEventArgs) _
    Handles ObjectDataSource1.Inserting

End Sub

この時点で、 InputParameters プロパティには、DetailsView から割り当てられた値を持つ ObjectDataSource InsertParameters のコレクションが含まれます。 これらのパラメーターの値を変更するには、 を使用 e.InputParameters("paramName") = valueします。 そのため、 と SupplierIDCategoryID値を 1 に設定するには、イベント ハンドラーをInserting次のように調整します。

Protected Sub ObjectDataSource1_Inserting _
    (sender As Object, e As ObjectDataSourceMethodEventArgs) _
    Handles ObjectDataSource1.Inserting

    e.InputParameters("CategoryID") = 1
    e.InputParameters("SupplierID") = 1
End Sub

今回は、新しい製品 (Acme Soda など) を追加するときに、 CategoryID 新しい製品の 列と SupplierID 列が 1 に設定されます (図 20 を参照)。

新しい製品の CategoryID と SupplierID の値が 1 に設定されるようになりました

図 20: 新製品の CategoryID 値と SupplierID 値が 1 に設定されるようになりました (クリックするとフルサイズの画像が表示されます)

まとめ

編集、挿入、および削除のプロセス中に、データ Web コントロールと ObjectDataSource の両方が、多くの事前および事後レベルのイベントを処理します。 このチュートリアルでは、事前レベルのイベントを調べ、これらを使用して入力パラメーターをカスタマイズするか、データ Web コントロールと ObjectDataSource のイベントの両方からデータ変更操作を完全に取り消す方法を確認しました。 次のチュートリアルでは、ポストレベル イベントのイベント ハンドラーの作成と使用について説明します。

幸せなプログラミング!

著者について

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

特別な感謝

このチュートリアル シリーズは、多くの役立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、Jackie Goor と Liz Shulok でした。 今後の MSDN 記事の確認に関心がありますか? その場合は、 に行mitchell@4GuysFromRolla.comをドロップしてください。