挿入、更新、削除に関連付けられているイベントを調べる (VB)
このチュートリアルでは、ASP.NET データ Web コントロールの挿入、更新、または削除操作の前後に発生するイベントの使用について説明します。 また、製品フィールドのサブセットのみを更新するように編集インターフェイスをカスタマイズする方法についても説明します。
はじめに
GridView、DetailsView、または FormView コントロールの組み込みの挿入、編集、または削除機能を使用する場合、エンド ユーザーが新しいレコードの追加または既存のレコードの更新または削除のプロセスを完了すると、さまざまな手順が発生します。 前のチュートリアルで説明したように、GridView で行を編集すると、[編集] ボタンが [更新] ボタンと [キャンセル] ボタンに置き換えられ、BoundFields がテキスト ボックスに変わります。 エンド ユーザーがデータを更新して [更新] をクリックすると、ポストバック時に次の手順が実行されます。
- 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 は の値 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 つの表示フィールド ProductName
と UnitPrice
のみを更新できます。 この編集インターフェイスは製品のフィールドのサブセットのみを提供するため、既存の 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
更新要求が失敗したことを示す が返されます。 それ以外の場合は、既存の製品レコードとProductName
UnitPrice
フィールドを適宜更新し、TableAdapter の Update()
メソッドを呼び出してインスタンスを渡して更新をProductsRow
コミットします。
このクラスに ProductsBLL
加えて、簡略化された GridView インターフェイスを作成する準備ができました。 フォルダー内の をDataModificationEvents.aspx
EditInsertDelete
開き、ページに GridView を追加します。 新しい ObjectDataSource を作成し、 へのメソッド マッピングGetProducts
とSelect()
、および Update()
入力パラメーターのみを受け取るオーバーロードへのUpdateProduct
メソッド マッピングで クラスをproductName
unitPrice
productID
使用ProductsBLL
するように構成します。 図 2 は、ObjectDataSource のメソッドをクラスのUpdate()
新しいUpdateProduct
メソッド オーバーロードにProductsBLL
マッピングするときのデータ ソースの作成ウィザードを示しています。
図 2: ObjectDataSource の Update()
メソッドを新しい UpdateProduct
オーバーロードにマップする (クリックするとフルサイズの画像が表示されます)
この例では、最初はデータを編集する必要がありますが、レコードを挿入または削除する機能は必要ないため、ObjectDataSource Insert()
の メソッドとメソッドを INSERT タブと Delete()
DELETE タブに移動し、ドロップダウン リストから (None) を選択して、クラスの 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 は製品の名前、価格、ID のみを持 UpdateParameters
ちますが、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
すようにするには、 と 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
設定します。
図 7: に応じて の プロパティと HtmlEncode
プロパティをDataFormatString
設定UnitPrice
します (クリックするとフルサイズの画像が表示されます)
この変更により、編集可能でない行は価格を通貨として書式設定します。ただし、編集された行には、通貨記号がなく、小数点以下 4 桁の値が表示されます。
図 8: 編集できない行が通貨値として書式設定されるようになりました (フルサイズの画像を表示する をクリックします)
プロパティで DataFormatString
指定された書式設定手順は、BoundField ApplyFormatInEditMode
の プロパティ True
を に設定することで編集インターフェイスに適用できます (既定値は False
です)。 このプロパティ True
を に設定します。
図 9: BoundField ApplyFormatInEditMode
の プロパティを にTrue
設定UnitPrice
します (クリックするとフルサイズの画像が表示されます)
この変更により、編集された行に表示される の値 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 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
イベント ハンドラーを使用してこのような入力を正しく解析する方法の両方を示しています。
図 11: 編集された行の UnitPrice
値が通貨として書式設定されるようになりました (フルサイズの画像を表示する をクリックします)
手順 2: 禁止NULL UnitPrices
テーブルの列の値を許可 NULL
するようにデータベースが Products
構成されている間、この特定の UnitPrice
ページにアクセスするユーザーが値を NULL
UnitPrice
指定できないようにすることができます。 つまり、ユーザーが製品行の編集時に値を入力 UnitPrice
できない場合は、結果をデータベースに保存するのではなく、このページを通じて、編集された製品に価格が指定されている必要があることをユーザーに通知するメッセージを表示します。
GridViewUpdateEventArgs
GridView RowUpdating
のイベント ハンドラーに渡される オブジェクトには、 にTrue
設定されている場合に更新プロセスを終了するプロパティが含まれていますCancel
。 イベント ハンドラーを RowUpdating
に設定True
e.Cancel
するように拡張し、コレクション内の値に の値がある場合UnitPrice
の理由を説明するメッセージをNewValues
Nothing
表示してみましょう。
まず、 という名前 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 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
ユーザーが価格を指定せずに製品を保存しようとすると、更新が取り消され、役に立つメッセージが表示されます。 データベース (およびビジネス ロジック) では が許可 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 Sub ObjectDataSource1_Inserting _
(sender As Object, e As ObjectDataSourceMethodEventArgs) _
Handles ObjectDataSource1.Inserting
End Sub
この時点で、 InputParameters
プロパティには、DetailsView から割り当てられた値を持つ ObjectDataSource InsertParameters
のコレクションが含まれます。 これらのパラメーターの値を変更するには、 を使用 e.InputParameters("paramName") = value
します。 そのため、 と SupplierID
のCategoryID
値を 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 を参照)。
図 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をドロップしてください。
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示