挿入、更新、削除に関連付けられているイベントを調べる (C#)
このチュートリアルでは、ASP.NET データ Web コントロールの挿入、更新、または削除操作の前後に発生するイベントの使用について説明します。 また、製品フィールドのサブセットのみを更新するように編集インターフェイスをカスタマイズする方法についても説明します。
はじめに
GridView、DetailsView、または FormView コントロールの組み込みの挿入、編集、または削除機能を使用する場合、エンド ユーザーが新しいレコードの追加または既存のレコードの更新または削除のプロセスを完了すると、さまざまな手順が実行されます。 前のチュートリアルで説明したように、GridView で行を編集すると、[編集] ボタンは [更新] ボタンと [キャンセル] ボタンに置き換えられ、BoundFields は TextBoxes になります。 エンド ユーザーがデータを更新し、[更新] をクリックすると、ポストバック時に次の手順が実行されます。
- GridView は、編集されたレコードの
UpdateParameters
一意の識別フィールド (プロパティを使用DataKeyNames
) とユーザーが入力した値を ObjectDataSource に設定します - GridView は ObjectDataSource の
Update()
メソッドを呼び出し、基になるオブジェクトの適切なメソッドを呼び出します (ProductsDAL.UpdateProduct
前のチュートリアルでは) - 更新された変更を含む基になるデータは、GridView にリバウンドされます
この一連の手順では、多数のイベントが発生し、必要に応じてカスタム ロジックを追加するイベント ハンドラーを作成できます。 たとえば、手順 1 より前の場合、GridView の RowUpdating
イベントが発生します。 検証エラーが発生した場合は、この時点で更新要求を取り消すことができます。 メソッドが Update()
呼び出されると、ObjectDataSource の Updating
イベントが発生し、 のいずれかの値を追加またはカスタマイズする機会が提供されます UpdateParameters
。 ObjectDataSource の基になるオブジェクトのメソッドの実行が完了すると、ObjectDataSource の Updated
イベントが発生します。 イベントの Updated
イベント ハンドラーは、影響を受けた行の数や例外が発生したかどうかなど、更新操作に関する詳細を調べることができます。 最後に、手順 2 の後に GridView のイベントが発生します。このイベントの RowUpdated
イベント ハンドラーは、先ほど実行した更新操作に関する追加情報を調べることができます。
図 1 は、GridView を更新するときのこの一連のイベントと手順を示しています。 図 1 のイベント パターンは、GridView を使用した更新に固有ではありません。 GridView、DetailsView、または FormView からデータを挿入、更新、または削除すると、データ Web コントロールと ObjectDataSource の両方に対して、前と後のレベルのイベントの同じシーケンスが生成されます。
図 1: GridView でデータを更新するときに発生する一連の事前イベントと事後イベント (フルサイズの画像を表示する をクリックします)
このチュートリアルでは、これらのイベントを使用して、ASP.NET データ Web コントロールの組み込みの挿入、更新、および削除機能を拡張する方法について説明します。 また、製品フィールドのサブセットのみを更新するように編集インターフェイスをカスタマイズする方法についても説明します。
手順 1: 製品とUnitPrice
フィールドをProductName
更新する
前のチュートリアルの編集インターフェイスでは、読み取り専用ではない すべての 製品フィールドを含める必要がありました。 データを更新するときに、GridView QuantityPerUnit
からフィールドを削除する場合、データ Web コントロールは ObjectDataSource の QuantityPerUnit
UpdateParameters
値を設定しません。 その後、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 つのフィールド ProductName
と UnitPrice
のみを更新できます。 この編集インターフェイスは製品のフィールドのサブセットのみを提供するため、既存の 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
返します。これは、製品情報の更新要求が失敗したことを示します。 それ以外の場合は、既存の製品レコードとProductName
UnitPrice
フィールドを適宜更新し、TableAdapter の Update()
メソッドを呼び出して インスタンスを渡して更新をProductsRow
コミットします。
このクラスへの ProductsBLL
追加により、簡略化された GridView インターフェイスを作成する準備ができました。 フォルダー内の をDataModificationEvents.aspx
EditInsertDelete
開き、ページに GridView を追加します。 新しい ObjectDataSource を作成し、 へのメソッド マッピングGetProducts
と、および Update()
productID
入力パラメーターのみを受け取るオーバーロードへのUpdateProduct
メソッド マッピングで クラスSelect()
をunitPrice
productName
使用ProductsBLL
するように構成します。 図 2 は、ObjectDataSource のメソッドをクラスのUpdate()
新しいUpdateProduct
メソッド オーバーロードにProductsBLL
マッピングするときのデータ ソースの作成ウィザードを示しています。
図 2: ObjectDataSource の Update()
メソッドを新しい UpdateProduct
オーバーロードにマップする (フルサイズの画像を表示する をクリックします)
この例では最初はデータを編集するだけで、レコードを挿入または削除する機能は必要ないため、ObjectDataSource Insert()
の メソッドとメソッドを INSERT タブと Delete()
DELETE タブに移動し、ドロップダウン リストから [なし] を選択して、クラスの ProductsBLL
メソッドにマップしないことを明示的に示します。
図 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
セクションはありませんInsertParameters
。Delete()
さらに、 メソッドは 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 が追加されています。
図 4: GridView には、製品の各フィールドの BoundField または CheckBoxField が含まれています (フルサイズの画像を表示する をクリックします)
エンド ユーザーが製品を編集し、その [更新] ボタンをクリックすると、GridView は読み取り専用ではないフィールドを列挙します。 次に、ObjectDataSource のコレクション内の対応するパラメーターの UpdateParameters
値を、ユーザーが入力した値に設定します。 対応するパラメーターがない場合、GridView によってコレクションに追加されます。 したがって、GridView に製品のすべてのフィールドに対して BoundFields と CheckBoxFields が含まれている場合、ObjectDataSource は、ObjectDataSource の宣言型マークアップで 3 つの入力パラメーターのみを指定しているにもかかわらず、これらすべてのパラメーターを受け取るオーバーロードを呼び出 UpdateProduct
します (図 5 を参照)。 同様に、GridView に読み取り専用でない製品フィールドの組み合わせがあり、オーバーロードの入力パラメーター UpdateProduct
に対応していない場合は、更新しようとすると例外が発生します。
図 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
設定します。
図 7: に応じて の DataFormatString
プロパティと HtmlEncode
プロパティを設定UnitPrice
します (フルサイズの画像を表示するには、 をクリックします)
この変更により、編集可能でない行は価格を通貨として書式設定します。ただし、編集された行には、通貨記号がなく、小数点以下 4 桁の値が表示されます。
図 8: 編集できない行が通貨値として書式設定されるようになりました (フルサイズの画像を表示する をクリックします)
プロパティで DataFormatString
指定された書式設定手順は、BoundField ApplyFormatInEditMode
の プロパティを に設定することで編集インターフェイスに true
適用できます (既定値は false
です)。 少し時間を取って、このプロパティを に設定します true
。
図 9: BoundField の プロパティを にtrue
設定UnitPrice
します (フルサイズのApplyFormatInEditMode
画像を表示するには、 をクリックします)
この変更により、編集された行に UnitPrice
表示される の値も通貨として書式設定されます。
図 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
イベント ハンドラーを使用してこのような入力を正しく解析する方法の両方を示しています。
図 11: 編集された行の UnitPrice
値が通貨として書式設定されるようになりました (フルサイズの画像を表示する をクリックします)
手順 2: 禁止NULL UnitPrices
テーブルの列の値を許可 NULL
するようにデータベースが Products
構成されている間、この特定の UnitPrice
ページにアクセスするユーザーが値を NULL
UnitPrice
指定できないようにすることができます。 つまり、ユーザーが製品行の編集時に値を入力 UnitPrice
できない場合は、結果をデータベースに保存するのではなく、このページを通じて、編集された製品に価格が指定されている必要があることをユーザーに通知するメッセージを表示します。
GridViewUpdateEventArgs
GridView RowUpdating
のイベント ハンドラーに渡される オブジェクトには、 にtrue
設定されている場合に更新プロセスを終了するプロパティが含まれていますCancel
。 イベント ハンドラーを RowUpdating
に設定true
e.Cancel
するように拡張し、コレクションnull
内の値が である場合の理由をUnitPrice
説明するメッセージをNewValues
表示してみましょう。
まず、 という名前 MustProvideUnitPriceMessage
のページに Label Web コントロールを追加します。 製品の更新時にユーザーが値の指定に失敗した場合、 UnitPrice
このラベル コントロールが表示されます。 Label の プロパティを "製品のText
価格を指定する必要があります" に設定します。また、次の定義を使用して、 という名前Warning
のStyles.css
新しい CSS クラスを作成しました。
.Warning
{
color: Red;
font-style: italic;
font-weight: bold;
font-size: x-large;
}
最後に、Label CssClass
の プロパティを に設定します Warning
。 この時点で、Designerは、図 12 に示すように、GridView の上に赤、太字、斜体、特大のフォント サイズで警告メッセージを表示する必要があります。
図 12: GridView の上にラベルが追加されました (フルサイズの画像を表示するをクリックします)
既定では、この Label は非表示にする必要があるため、イベント ハンドラーでそのプロパティを Page_Load
にfalse
設定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;
}
}
ユーザーが価格を指定せずに製品を保存しようとすると、更新が取り消され、役に立つメッセージが表示されます。 データベース (およびビジネス ロジック) では が許可 NULL
UnitPrice
されますが、この特定の ASP.NET ページでは許可されません。
図 13: ユーザーを空白のままに UnitPrice
することはできません (フルサイズの画像を表示する場合はクリックします)
ここまでは、GridView の イベントを使用して、ObjectDataSource UpdateParameters
のRowUpdating
コレクションに割り当てられているパラメーター値をプログラムで変更する方法と、更新プロセスを完全に取り消す方法について説明しました。 これらの概念は DetailsView コントロールと FormView コントロールに引き継がれ、挿入と削除にも適用されます。
これらのタスクは、ObjectDataSource レベルで、そのInserting
Updating
イベント、、および Deleting
イベントのイベント ハンドラーを使用して実行することもできます。 これらのイベントは、基になるオブジェクトの関連付けられたメソッドが呼び出される前に発生し、入力パラメーター コレクションを変更したり、操作を完全に取り消したりする最後の機会を提供します。 これら 3 つのイベントのイベント ハンドラーには、次の 2 つのプロパティを持つ ObjectDataSourceMethodEventArgs 型のオブジェクトが渡されます。
- Cancel (に設定されている場合) は
true
、実行されている操作を取り消します - InputParameters。イベント ハンドラーが 、、または イベント用かどうかに応じて、
Updating
またはDeleting
DeleteParameters
のコレクションInsertParameters
UpdateParameters
です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] タブに移動すると、マッピングが存在することがわかります。 これは、 ProductsBLL
AddProduct
メソッドと DeleteProduct
メソッドが 属性をDataObjectMethodAttribute
使用して、 と Delete()
の既定のメソッドInsert()
であることを示しているためです。 そのため、ObjectDataSource ウィザードは、他の値が明示的に指定されていない限り、ウィザードを実行するたびにこれらを選択します。
メソッドは Insert()
メソッドを指したまま AddProduct
にしますが、DELETE タブのドロップダウン リストを (None) に設定します。
図 14: INSERT タブの Drop-Down リストを メソッドに AddProduct
設定します (フルサイズの画像を表示する 場合は クリックします)
図 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 ProductName
UnitPrice
と - と 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) の名前と価格が一覧表示されます。 ただし、必要なのは、ユーザーが新しい製品をデータベースにすばやく追加するための手段を提供する挿入インターフェイスです。
図 16: DetailsView は現在、Read-Only モードでレンダリングされています (フルサイズの画像を表示するには、ここをクリックします)
DetailsView を挿入モードで表示するには、 プロパティを に設定 DefaultMode
する Inserting
必要があります。 これにより、最初にアクセスしたときに DetailsView が挿入モードでレンダリングされ、新しいレコードを挿入した後も保持されます。 図 17 に示すように、このような DetailsView には、新しいレコードを追加するためのクイック インターフェイスが用意されています。
図 17: DetailsView は、新しい製品を迅速に追加するためのインターフェイスを提供します (フルサイズの画像を表示する をクリックします)
ユーザーが製品名と価格 (図 17 のように "Acme Water" や 1.99 など) を入力して [挿入] をクリックすると、ポストバックが続き、挿入ワークフローが開始され、新しい製品レコードがデータベースに追加されます。 DetailsView は挿入インターフェイスを維持し、図 18 に示すように、GridView は新しい製品を含めるためにデータ ソースに自動的にリバウンドされます。
図 18: 製品 "アクメ ウォーター" がデータベースに追加されました
図 18 の GridView には表示されませんが、DetailsView インターフェイス CategoryID
、SupplierID
QuantityPerUnit
などから欠落している製品フィールドには、データベース値が割り当てられますNULL
。 これは、次の手順を実行して確認できます。
- Visual Studio のサーバー エクスプローラーに移動する
- データベース ノードの
NORTHWND.MDF
展開 - データベース テーブル ノードを
Products
右クリックします - [テーブル データの表示] を選択します
これにより、テーブル内 Products
のすべてのレコードが一覧表示されます。 図 19 に示すように、、、 以外ProductID
ProductName
UnitPrice
のすべての新製品の列には値があります。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
のオブジェクトであることに注意してください。このオブジェクトには、パラメーター コレクション () にアクセスするためのプロパティと、操作を取り消すプロパティ (InputParameters
Cancel
) があります。
protected void ObjectDataSource1_Inserting
(object sender, ObjectDataSourceMethodEventArgs e)
{
}
この時点で、 InputParameters
プロパティには、DetailsView から割り当てられた値を含む ObjectDataSource InsertParameters
のコレクションが含まれます。 これらのパラメーターの値を変更するには、 を使用 e.InputParameters["paramName"] = value
します。 したがって、 と SupplierID
のCategoryID
値を 1 に設定するには、イベント ハンドラーをInserting
次のように調整します。
protected void ObjectDataSource1_Inserting
(object sender, ObjectDataSourceMethodEventArgs e)
{
e.InputParameters["CategoryID"] = 1;
e.InputParameters["SupplierID"] = 1;
}
今回は新製品 (Acme Soda など) を追加するときに、 CategoryID
新しい製品の 列と SupplierID
列が 1 に設定されます (図 20 を参照)。
図 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行をドロップしてください。
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示