Share via


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

作成者: Scott Mitchell

PDF のダウンロード

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

はじめに

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

  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 はビジネス ロジック レイヤー (BLL) メソッドにUpdateProduct値を渡nullします。これにより、編集されたデータベース レコードの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 bool UpdateProduct(string productName, decimal? unitPrice, int productID)
{
    Northwind.ProductsDataTable products = Adapter.GetProductByProductID(productID);
    if (products.Count == 0)
        // no matching record found, return false
        return false;

    Northwind.ProductsRow product = products[0];

    product.ProductName = productName;
    if (unitPrice == null) product.SetUnitPriceNull();
      else product.UnitPrice = unitPrice.Value;

    // Update the product record
    int rowsAffected = Adapter.Update(product);

    // Return true if precisely one row was updated, otherwise false
    return rowsAffected == 1;
}

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

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

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

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

この例では最初はデータを編集するだけで、レコードを挿入または削除する機能は必要ないため、ObjectDataSource Insert() の メソッドとメソッドを INSERT タブと Delete() DELETE タブに移動し、ドロップダウン リストから [なし] を選択して、クラスの 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 には UpdateParameters 製品の名前、価格、ID のみが含まれますが、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すには、GridView を と UnitPriceの編集可能なフィールドにProductName制限する必要があります。 これを実現するには、他の 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 つだけあります。 これは、 productID 入力パラメーターが主キー値であり、編集された行の プロパティの値を DataKeyNames 介して渡されるためです。

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

インターフェイスを使用すると、製品の名前と価格のみを編集できます

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

注意

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

書式設定のUnitPrice改善

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

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

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

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

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

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

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

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

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

この変更により、編集された行に 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 void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
  if (e.NewValues["UnitPrice"] != null)
    e.NewValues["UnitPrice"] =
        decimal.Parse(e.NewValues["UnitPrice"].ToString(),
            System.Globalization.NumberStyles.Currency);
}

ユーザーが値 ("$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するように拡張し、コレクションnull内の値が である場合の理由をUnitPrice説明するメッセージをNewValues表示してみましょう。

まず、 という名前 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 void Page_Load(object sender, EventArgs e)
{
    MustProvideUnitPriceMessage.Visible = false;
}

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

protected void GridView1_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
    if (e.NewValues["UnitPrice"] != null)
    {
        e.NewValues["UnitPrice"] =
            decimal.Parse(e.NewValues["UnitPrice"].ToString(),
                System.Globalization.NumberStyles.Currency);
    }
    else
    {
        // Show the Label
        MustProvideUnitPriceMessage.Visible = true;

        // Cancel the update
        e.Cancel = true;
    }
}

ユーザーが価格を指定せずに製品を保存しようとすると、更新が取り消され、役に立つメッセージが表示されます。 データベース (およびビジネス ロジック) では が許可 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 void ObjectDataSource1_Inserting
    (object sender, ObjectDataSourceMethodEventArgs e)
{

}

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

protected void ObjectDataSource1_Inserting
    (object sender, ObjectDataSourceMethodEventArgs e)
{
    e.InputParameters["CategoryID"] = 1;
    e.InputParameters["SupplierID"] = 1;
}

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

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

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

まとめ

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

プログラミングに満足!

著者について

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

特別な感謝

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