GridView のフッターから新しいレコードを挿入する (C#)
GridView コントロールでは、データの新しいレコードを挿入するための組み込みのサポートは提供されませんが、このチュートリアルでは、挿入インターフェイスを含むように GridView を拡張する方法について説明します。
はじめに
「 データの挿入、更新、および削除の概要 」チュートリアルで説明したように、GridView、DetailsView、および FormView Web コントロールには、それぞれ組み込みのデータ変更機能が含まれています。 宣言型データ ソース コントロールと共に使用する場合、これら 3 つの Web コントロールは、1 行のコードを記述しなくても、データを変更するように迅速かつ簡単に構成できます。 残念ながら、DetailsView コントロールと FormView コントロールのみが、組み込みの挿入、編集、および削除機能を提供します。 GridView では、編集と削除のサポートのみが提供されます。 しかし、少しエルボグリースを使用すると、GridViewを拡張して挿入インターフェイスを含めることができます。
GridView に挿入機能を追加する際には、新しいレコードの追加方法を決定し、挿入インターフェイスを作成し、新しいレコードを挿入するコードを記述する必要があります。 このチュートリアルでは、挿入インターフェイスを GridView のフッター行に追加する方法について説明します (図 1 を参照)。 各列のフッター セルには、適切なデータ 収集ユーザー インターフェイス要素 (製品名の TextBox、仕入先の DropDownList など) が含まれます。 また、[追加] ボタンの列も必要です。このボタンをクリックするとポストバックが発生し、フッター行に指定された値を Products
使用して新しいレコードがテーブルに挿入されます。
図 1: フッター行には、新しい製品を追加するためのインターフェイスが用意されています (クリックするとフルサイズの画像が表示されます)
手順 1: GridView で製品情報を表示する
GridView のフッターに挿入インターフェイスを作成する前に、まず、データベース内の製品を一覧表示するページに GridView を追加することに焦点を当ててみましょう。 まず、フォルダー内のページをInsertThroughFooter.aspx
EnhancedGridView
開き、GridView をツールボックスからDesignerにドラッグし、GridView の ID
プロパティを にProducts
設定します。 次に、GridView のスマート タグを使用して、 という名前 ProductsDataSource
の新しい ObjectDataSource にバインドします。
図 2: 名前付きの ProductsDataSource
新しい ObjectDataSource を作成する (クリックするとフルサイズの画像が表示されます)
クラス s GetProducts()
メソッドを使用して製品情報をProductsBLL
取得するように ObjectDataSource を構成します。 このチュートリアルでは、挿入機能の追加に重点を置き、編集と削除について心配しないようにします。 したがって、INSERT タブのドロップダウン リストが に AddProduct()
設定されていること、および UPDATE タブと DELETE タブのドロップダウン リストが (None) に設定されていることを確認します。
図 3: メソッドを AddProduct
ObjectDataSource の Insert()
メソッドにマップする (クリックするとフルサイズの画像が表示されます)
図 4: [UPDATE] タブと [DELETE] タブ Drop-Down Lists を [(なし)] に設定します (フルサイズの画像を表示するには、ここをクリックします)
ObjectDataSource のデータ ソースの構成ウィザードを完了すると、Visual Studio によって、対応する各データ フィールドのフィールドが GridView に自動的に追加されます。 ここでは、Visual Studio によって追加されたすべてのフィールドをそのまま使用します。 このチュートリアルの後半では、新しいレコードを追加するときに値を指定する必要がないフィールドの一部を削除します。
データベースには 80 個近くの製品があるため、ユーザーは Web ページの下部までスクロールして新しいレコードを追加する必要があります。 そのため、ページングを有効にして、挿入インターフェイスの表示とアクセスを向上させます。 ページングを有効にするには、GridView のスマート タグから [ページングを有効にする] チェック ボックスをチェックします。
この時点で、GridView と ObjectDataSource の宣言型マークアップは次のようになります。
<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ProductsDataSource"
AllowPaging="True" EnableViewState="False">
<Columns>
<asp:BoundField DataField="ProductID" HeaderText="ProductID"
InsertVisible="False" ReadOnly="True"
SortExpression="ProductID" />
<asp:BoundField DataField="ProductName" HeaderText="ProductName"
SortExpression="ProductName" />
<asp:BoundField DataField="SupplierID" HeaderText="SupplierID"
SortExpression="SupplierID" />
<asp:BoundField DataField="CategoryID" HeaderText="CategoryID"
SortExpression="CategoryID" />
<asp:BoundField DataField="QuantityPerUnit" HeaderText="QuantityPerUnit"
SortExpression="QuantityPerUnit" />
<asp:BoundField DataField="UnitPrice" HeaderText="UnitPrice"
SortExpression="UnitPrice" />
<asp:BoundField DataField="UnitsInStock" HeaderText="UnitsInStock"
SortExpression="UnitsInStock" />
<asp:BoundField DataField="UnitsOnOrder" HeaderText="UnitsOnOrder"
SortExpression="UnitsOnOrder" />
<asp:BoundField DataField="ReorderLevel" HeaderText="ReorderLevel"
SortExpression="ReorderLevel" />
<asp:CheckBoxField DataField="Discontinued" HeaderText="Discontinued"
SortExpression="Discontinued" />
<asp:BoundField DataField="CategoryName" HeaderText="CategoryName"
ReadOnly="True" SortExpression="CategoryName" />
<asp:BoundField DataField="SupplierName" HeaderText="SupplierName"
ReadOnly="True" SortExpression="SupplierName" />
</Columns>
</asp:GridView>
<asp:ObjectDataSource ID="ProductsDataSource" runat="server"
InsertMethod="AddProduct" OldValuesParameterFormatString="original_{0}"
SelectMethod="GetProducts" TypeName="ProductsBLL">
<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>
図 5: すべての製品データ フィールドが Paged GridView に表示される (フルサイズの画像を表示する をクリックします)
手順 2: フッター行を追加する
GridView には、ヘッダー行とデータ行に加えて、フッター行が含まれます。 ヘッダー行とフッター行は、GridView ShowHeader
ShowFooter
の と プロパティの値に応じて表示されます。 フッター行を表示するには、 プロパティを ShowFooter
に true
設定します。 図 6 に示すように、 プロパティを ShowFooter
に設定すると true
、フッター行がグリッドに追加されます。
図 6: フッター行を表示するには、 を にTrue
設定ShowFooter
します (クリックするとフルサイズの画像が表示されます)
フッター行の背景色は濃い赤色であることに注意してください。 これは、 ObjectDataSource を使用したデータの表示に関するチュートリアルで作成し、すべてのページに適用した DataWebControls テーマが原因です。 具体的には、ファイルは GridView.skin
CSS クラスを FooterStyle
使用するように プロパティを FooterStyle
構成します。 クラスは FooterStyle
、 で Styles.css
次のように定義されます。
.FooterStyle
{
background-color: #a33;
color: White;
text-align: right;
}
注意
前のチュートリアルでは、GridView のフッター行を使用して調べてきました。 必要に応じて、 GridView のフッターの概要情報の表示 に関するチュートリアルを参照して、更新を行います。
プロパティを にShowFooter
true
設定した後、しばらくしてブラウザーで出力を表示します。 現在、フッター行にはテキストや Web コントロールは含まれません。 手順 3 では、適切な挿入インターフェイスが含まれるように、各 GridView フィールドのフッターを変更します。
図 7: ページング インターフェイス コントロールの上に空のフッター行が表示されます (フルサイズの画像を表示する をクリックします)。
手順 3: フッター行をカスタマイズする
GridView コントロールのチュートリアルの TemplateFields の使用に関するチュートリアルでは、TemplateFields (BoundFields や CheckBoxFields ではなく) を使用して、特定の GridView 列の表示を大幅にカスタマイズする方法について説明しました。「データ変更インターフェイスのカスタマイズ」で、TemplateFields を使用して GridView の編集インターフェイスをカスタマイズする方法について説明しました。 TemplateField は、特定の種類の行に使用されるマークアップ、Web コントロール、およびデータバインド構文の組み合わせを定義する多数のテンプレートで構成されていることを思い出してください。 たとえば、 は ItemTemplate
読み取り専用行に使用されるテンプレートを指定し EditItemTemplate
、 では編集可能な行のテンプレートを定義します。
と EditItemTemplate
に加えてItemTemplate
、TemplateField にはフッター行の内容を指定する も含まれていますFooterTemplate
。 したがって、 にインターフェイスを挿入する各フィールドに必要な Web コントロールを FooterTemplate
追加できます。 まず、GridView 内のすべてのフィールドを TemplateFields に変換します。 これを行うには、GridView のスマート タグの [列の編集] リンクをクリックし、左下隅にある各フィールドを選択し、[このフィールドを TemplateField に変換する] リンクをクリックします。
図 8: 各フィールドを TemplateField に変換する
[このフィールドを TemplateField に変換する] をクリックすると、現在のフィールド型が同等の TemplateField に変わります。 たとえば、各 BoundField は TemplateField ItemTemplate
に置き換えられ、対応するデータ フィールドを表示する Label と EditItemTemplate
、テキスト ボックス (TextBox) にデータ フィールドを表示する を含む が含まれます。 ProductName
BoundField は、次の TemplateField マークアップに変換されています。
<asp:TemplateField HeaderText="ProductName" SortExpression="ProductName">
<EditItemTemplate>
<asp:TextBox ID="TextBox1" runat="server"
Text='<%# Bind("ProductName") %>'></asp:TextBox>
</EditItemTemplate>
<ItemTemplate>
<asp:Label ID="Label2" runat="server"
Text='<%# Bind("ProductName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
同様に Discontinued
、CheckBoxField は、CheckBox Web コントロールを含む ItemTemplate
EditItemTemplate
TemplateField に変換されています ( ItemTemplate
CheckBox が無効になっています)。 読み取り専用ProductID
の BoundField は、 と EditItemTemplate
の両方ItemTemplate
で Label コントロールを持つ TemplateField に変換されています。 つまり、既存の GridView フィールドを TemplateField に変換すると、既存のフィールドの機能を失うことなく、よりカスタマイズ可能な TemplateField にすばやく簡単に切り替えることができます。
使用している GridView では編集がサポートされていないため、各 TemplateField から を EditItemTemplate
自由に削除して、 だけを ItemTemplate
残してください。 これを行った後、GridView の宣言型マークアップは次のようになります。
<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ProductsDataSource"
AllowPaging="True" EnableViewState="False" ShowFooter="True">
<Columns>
<asp:TemplateField HeaderText="ProductID" InsertVisible="False"
SortExpression="ProductID">
<ItemTemplate>
<asp:Label ID="Label1" runat="server"
Text='<%# Bind("ProductID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="ProductName" SortExpression="ProductName">
<ItemTemplate>
<asp:Label ID="Label2" runat="server"
Text='<%# Bind("ProductName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="SupplierID" SortExpression="SupplierID">
<ItemTemplate>
<asp:Label ID="Label3" runat="server"
Text='<%# Bind("SupplierID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="CategoryID" SortExpression="CategoryID">
<ItemTemplate>
<asp:Label ID="Label4" runat="server"
Text='<%# Bind("CategoryID") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="QuantityPerUnit"
SortExpression="QuantityPerUnit">
<ItemTemplate>
<asp:Label ID="Label5" runat="server"
Text='<%# Bind("QuantityPerUnit") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="UnitPrice" SortExpression="UnitPrice">
<ItemTemplate>
<asp:Label ID="Label6" runat="server"
Text='<%# Bind("UnitPrice") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="UnitsInStock"
SortExpression="UnitsInStock">
<ItemTemplate>
<asp:Label ID="Label7" runat="server"
Text='<%# Bind("UnitsInStock") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="UnitsOnOrder"
SortExpression="UnitsOnOrder">
<ItemTemplate>
<asp:Label ID="Label8" runat="server"
Text='<%# Bind("UnitsOnOrder") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="ReorderLevel"
SortExpression="ReorderLevel">
<ItemTemplate>
<asp:Label ID="Label9" runat="server"
Text='<%# Bind("ReorderLevel") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Discontinued"
SortExpression="Discontinued">
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server"
Checked='<%# Bind("Discontinued") %>' Enabled="false" />
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="CategoryName"
SortExpression="CategoryName">
<ItemTemplate>
<asp:Label ID="Label10" runat="server"
Text='<%# Bind("CategoryName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="SupplierName"
SortExpression="SupplierName">
<ItemTemplate>
<asp:Label ID="Label11" runat="server"
Text='<%# Bind("SupplierName") %>'></asp:Label>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
各 GridView フィールドが TemplateField に変換されたので、各フィールド FooterTemplate
の に適切な挿入インターフェイスを入力できます。 一部のフィールドには挿入インターフェイス (ProductID
たとえば) がありません。その他のフィールドは、新しい製品の情報を収集するために使用される Web コントロールによって異なります。
編集インターフェイスを作成するには、GridView のスマート タグから [テンプレートの編集] リンクを選択します。 次に、ドロップダウン リストから適切なフィールドをFooterTemplate
選択し、ツールボックスからDesignerに適切なコントロールをドラッグします。
図 9: 各フィールドに適切な挿入インターフェイスを追加する (フルサイズのFooterTemplate
画像を表示する をクリックします)
次の箇条書きでは、追加する挿入インターフェイスを指定して、GridView フィールドを列挙します。
ProductID
なし。ProductName
TextBox を追加し、 をID
にNewProductName
設定します。 RequiredFieldValidator コントロールを追加して、ユーザーが新しい製品名の値を入力するようにします。SupplierID
なし。CategoryID
なし。QuantityPerUnit
TextBox を追加し、 をID
にNewQuantityPerUnit
設定します。UnitPrice
という名前NewUnitPrice
の TextBox と CompareValidator を追加して、入力した値が 0 以上の通貨値であることを確認します。UnitsInStock
が に設定されているID
TextBox を使用しますNewUnitsInStock
。 入力した値が 0 以上の整数値であることを保証する CompareValidator を含めます。UnitsOnOrder
が に設定されているID
TextBox を使用しますNewUnitsOnOrder
。 入力した値が 0 以上の整数値であることを保証する CompareValidator を含めます。ReorderLevel
が に設定されているID
TextBox を使用しますNewReorderLevel
。 入力した値が 0 以上の整数値であることを保証する CompareValidator を含めます。Discontinued
CheckBox を追加し、 をID
にNewDiscontinued
設定します。CategoryName
DropDownList を追加し、 をID
に設定しますNewCategoryID
。 これを という名前CategoriesDataSource
の新しい ObjectDataSource にバインドし、クラス sGetCategories()
メソッドをCategoriesBLL
使用するように構成します。 値としてデータ フィールドをCategoryName
使用して、DropDownListListItem
にデータ フィールドをCategoryID
表示してもらいます。SupplierName
DropDownList を追加し、その をID
にNewSupplierID
設定します。 これを という名前SuppliersDataSource
の新しい ObjectDataSource にバインドし、クラス sGetSuppliers()
メソッドをSuppliersBLL
使用するように構成します。 値としてデータ フィールドをCompanyName
使用して、DropDownListListItem
にデータ フィールドをSupplierID
表示してもらいます。
各検証コントロールについて、 プロパティを ForeColor
クリアして、CSS クラスの白い前景色が既定の赤の代わりに使用されるように FooterStyle
します。 また、 ErrorMessage
詳細な説明には プロパティを使用しますが、 プロパティを Text
アスタリスクに設定します。 検証コントロールのテキストによって挿入インターフェイスが 2 行に折り返されないようにするには、検証コントロールを使用する s ごとに FooterTemplate
s Wrap
プロパティを false に設定FooterStyle
します。 最後に、GridView の下に ValidationSummary コントロールを追加し、そのプロパティを ShowMessageBox
に true
設定し、その ShowSummary
プロパティを に false
設定します。
新しい製品を追加するときは、 と SupplierID
を指定CategoryID
する必要があります。 この情報は、 フィールドと SupplierName
フィールドのフッター セルCategoryName
の DropDownLists を通じてキャプチャされます。 グリッドのデータ行では、ユーザーが ID 値ではなくカテゴリ名とサプライヤー名を表示することに関心がある可能性が高いため、 と SupplierID
TemplateFields ではなくCategoryID
、これらのフィールドを使用することを選択しました。 と SupplierID
のCategoryID
値は、 および SupplierName
フィールドの挿入インターフェイスでCategoryName
キャプチャされるようになったため、GridView から および SupplierID
TemplateFields を削除CategoryID
できます。
同様に、 ProductID
は新しい製品を追加するときに使用されないため ProductID
、TemplateField も削除できます。 ただし、グリッド内のフィールドはそのまま ProductID
にします。 挿入インターフェイスを構成する TextBoxes、DropDownLists、CheckBoxes、および検証コントロールに加えて、[追加] ボタンも必要です。このボタンをクリックすると、新しい製品をデータベースに追加するロジックが実行されます。 手順 4 では、TemplateField の FooterTemplate
挿入インターフェイスに [追加] ボタンをProductID
含めます。
さまざまな GridView フィールドの外観を自由に改善してください。 たとえば、値をUnitPrice
通貨として書式設定し、、UnitsOnOrder
、および フィールドをUnitsInStock
右揃えにしてReorderLevel
、TemplateFields のHeaderText
値を更新することができます。
にインターフェイス FooterTemplate
を挿入し、、、 TemplateFields を削除 SupplierID
し CategoryID
、TemplateFields を書式設定して配置することでグリッドの美しさを向上させるスルーを作成した後、GridView の宣言型マークアップは次のようになります。
<asp:GridView ID="Products" runat="server" AutoGenerateColumns="False"
DataKeyNames="ProductID" DataSourceID="ProductsDataSource"
AllowPaging="True" EnableViewState="False" ShowFooter="True">
<Columns>
<asp:TemplateField HeaderText="ProductID" InsertVisible="False"
SortExpression="ProductID">
<ItemTemplate>
<asp:Label ID="Label1" runat="server"
Text='<%# Bind("ProductID") %>'></asp:Label>
</ItemTemplate>
<ItemStyle HorizontalAlign="Center" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Product" SortExpression="ProductName">
<ItemTemplate>
<asp:Label ID="Label2" runat="server"
Text='<%# Bind("ProductName") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox ID="NewProductName" runat="server"></asp:TextBox>
<asp:RequiredFieldValidator ID="RequiredFieldValidator1"
runat="server" ControlToValidate="NewProductName"
Display="Dynamic" ForeColor="
ErrorMessage="You must enter a name for the new product.">
* </asp:RequiredFieldValidator>
</FooterTemplate>
<FooterStyle Wrap="False" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Category" SortExpression="CategoryName">
<ItemTemplate>
<asp:Label ID="Label10" runat="server"
Text='<%# Bind("CategoryName") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:DropDownList ID="NewCategoryID" runat="server"
DataSourceID="CategoriesDataSource"
DataTextField="CategoryName" DataValueField="CategoryID">
</asp:DropDownList>
<asp:ObjectDataSource ID="CategoriesDataSource" runat="server"
OldValuesParameterFormatString="original_{0}"
SelectMethod="GetCategories" TypeName="CategoriesBLL">
</asp:ObjectDataSource>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Supplier" SortExpression="SupplierName">
<ItemTemplate>
<asp:Label ID="Label11" runat="server"
Text='<%# Bind("SupplierName") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:DropDownList ID="NewSupplierID" runat="server"
DataSourceID="SuppliersDataSource"
DataTextField="CompanyName" DataValueField="SupplierID">
</asp:DropDownList><asp:ObjectDataSource ID="SuppliersDataSource"
runat="server" OldValuesParameterFormatString="original_{0}"
SelectMethod="GetSuppliers" TypeName="SuppliersBLL">
</asp:ObjectDataSource>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Qty/Unit" SortExpression="QuantityPerUnit">
<ItemTemplate>
<asp:Label ID="Label5" runat="server"
Text='<%# Bind("QuantityPerUnit") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox ID="NewQuantityPerUnit" runat="server"></asp:TextBox>
</FooterTemplate>
</asp:TemplateField>
<asp:TemplateField HeaderText="Price" SortExpression="UnitPrice">
<ItemTemplate>
<asp:Label ID="Label6" runat="server"
Text='<%# Bind("UnitPrice", "{0:c}") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
$<asp:TextBox ID="NewUnitPrice" runat="server" Columns="8" />
<asp:CompareValidator ID="CompareValidator1" runat="server"
ControlToValidate="NewUnitPrice"
ErrorMessage="You must enter a valid currency value greater than
or equal to 0.00. Do not include the currency symbol."
ForeColor="" Operator="GreaterThanEqual" Type="Currency"
ValueToCompare="0" Display="Dynamic">
* </asp:CompareValidator>
</FooterTemplate>
<ItemStyle HorizontalAlign="Right" />
<FooterStyle Wrap="False" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Units In Stock"
SortExpression="Units In Stock">
<ItemTemplate>
<asp:Label ID="Label7" runat="server"
Text='<%# Bind("UnitsInStock") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox ID="NewUnitsInStock" runat="server" Columns="5" />
<asp:CompareValidator ID="CompareValidator2" runat="server"
ControlToValidate="NewUnitsInStock" Display="Dynamic"
ErrorMessage="You must enter a valid numeric value for units
in stock that's greater than or equal to zero."
ForeColor="" Operator="GreaterThanEqual" Type="Integer"
ValueToCompare="0">*</asp:CompareValidator>
</FooterTemplate>
<ItemStyle HorizontalAlign="Right" />
<FooterStyle Wrap="False" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Units On Order" SortExpression="UnitsOnOrder">
<ItemTemplate>
<asp:Label ID="Label8" runat="server"
Text='<%# Bind("UnitsOnOrder") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox ID="NewUnitsOnOrder" runat="server" Columns="5" />
<asp:CompareValidator ID="CompareValidator3" runat="server"
ControlToValidate="NewUnitsOnOrder" Display="Dynamic"
ErrorMessage="You must enter a valid numeric value for units on
order that's greater than or equal to zero."
ForeColor="" Operator="GreaterThanEqual" Type="Integer"
ValueToCompare="0">*</asp:CompareValidator>
</FooterTemplate>
<ItemStyle HorizontalAlign="Right" />
<FooterStyle Wrap="False" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Reorder Level" SortExpression="ReorderLevel">
<ItemTemplate>
<asp:Label ID="Label9" runat="server"
Text='<%# Bind("ReorderLevel") %>'></asp:Label>
</ItemTemplate>
<FooterTemplate>
<asp:TextBox ID="NewReorderLevel" runat="server" Columns="5" />
<asp:CompareValidator ID="CompareValidator4" runat="server"
ControlToValidate="NewReorderLevel" Display="Dynamic"
ErrorMessage="You must enter a valid numeric value for reorder
level that's greater than or equal to zero."
ForeColor="" Operator="GreaterThanEqual" Type="Integer"
ValueToCompare="0">*</asp:CompareValidator>
</FooterTemplate>
<ItemStyle HorizontalAlign="Right" />
<FooterStyle Wrap="False" />
</asp:TemplateField>
<asp:TemplateField HeaderText="Discontinued" SortExpression="Discontinued">
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" runat="server"
Checked='<%# Bind("Discontinued") %>' Enabled="false" />
</ItemTemplate>
<FooterTemplate>
<asp:CheckBox ID="NewDiscontinued" runat="server" />
</FooterTemplate>
<ItemStyle HorizontalAlign="Center" />
<FooterStyle HorizontalAlign="Center" />
</asp:TemplateField>
</Columns>
</asp:GridView>
ブラウザーで表示すると、GridView のフッター行に、完成した挿入インターフェイスが含まれるようになりました (図 10 を参照)。 この時点で、挿入インターフェイスには、ユーザーが新しい製品のデータを入力し、データベースに新しいレコードを挿入することを示す手段は含まれていません。 また、フッターに入力されたデータがデータベースの新しいレコード Products
にどのように変換されるかについては、まだ説明していません。 手順 4 では、挿入インターフェイスに [追加] ボタンを含める方法と、クリックしたときにポストバックでコードを実行する方法について説明します。 手順 5 では、フッターのデータを使用して新しいレコードを挿入する方法を示します。
図 10: GridView フッターは、新しいレコードを追加するためのインターフェイスを提供します (フルサイズの画像を表示する をクリックします)
手順 4: 挿入インターフェイスに追加ボタンを含める
フッター行の挿入インターフェイスには現在、新しい製品の情報の入力が完了したことをユーザーが示す手段がないため、挿入インターフェイスのどこかに [追加] ボタンを含める必要があります。 これは、既存 FooterTemplate
の の 1 つに配置することも、この目的のためにグリッドに新しい列を追加することもできます。 このチュートリアルでは、TemplateField の FooterTemplate
に [追加] ボタンをProductID
配置します。
Designerから、GridView のスマート タグの [テンプレートの編集] リンクをクリックし、ドロップダウン リストからフィールドをFooterTemplate
選択ProductID
します。 ボタン Web コントロール (または必要に応じて LinkButton または ImageButton) をテンプレートに追加し、その ID を に AddProduct
設定し、その CommandName
ID を Insert に、その Text
プロパティを Add に設定します (図 11 を参照)。
図 11: TemplateFields に [追加] ボタンをProductID
配置します (フルサイズのFooterTemplate
画像を表示する場合はクリックします)
[追加] ボタンを含めたら、ブラウザーでページをテストします。 挿入インターフェイスで無効なデータを含む [追加] ボタンをクリックすると、ポストバックがショートし、ValidationSummary コントロールが無効なデータを示します (図 12 を参照)。 適切なデータを入力すると、[追加] ボタンをクリックするとポストバックが発生します。 ただし、データベースにレコードは追加されません。 実際に挿入を実行するには、コードを少し記述する必要があります。
図 12: 挿入インターフェイスに無効なデータがある場合、[ボタンのポストバックの追加] がショート サーキット (フルサイズの画像を表示する場合をクリックします)
注意
挿入インターフェイスの検証コントロールが検証グループに割り当てされませんでした。 挿入インターフェイスがページ上の検証コントロールの唯一のセットである限り、これは正常に動作します。 ただし、ページ上に他の検証コントロール (グリッドの編集インターフェイスの検証コントロールなど) がある場合は、挿入インターフェイスの検証コントロールと [ボタンの追加] プロパティに、これらのコントロールを特定の ValidationGroup
検証グループに関連付けるために同じ値を割り当てる必要があります。 ページ 上の検証コントロールとボタンを検証グループに分割する 方法の詳細については、「ASP.NET 2.0 での検証コントロールの分割」を参照してください。
手順 5: テーブルに新しいレコードを挿入するProducts
GridView の組み込みの編集機能を利用すると、GridView は更新の実行に必要なすべての作業を自動的に処理します。 特に、[更新] ボタンをクリックすると、編集インターフェイスから ObjectDataSource s コレクションのパラメーターに入力された値がコピーされ、ObjectDataSource s UpdateParameters
Update()
メソッドを呼び出して更新が開始されます。 GridView にはこのような挿入用の組み込み機能がないため、ObjectDataSource s メソッドを呼び出し、挿入インターフェイスから ObjectDataSource InsertParameters
のInsert()
コレクションに値をコピーするコードを実装する必要があります。
この挿入ロジックは、[追加] ボタンをクリックした後に実行する必要があります。 「GridView でのボタンの追加と応答」チュートリアルで説明したように、GridView の Button、LinkButton、ImageButton がクリックされるたびに、GridView のRowCommand
イベントはポストバック時に発生します。 このイベントは、フッター行の [追加] ボタンなど、Button、LinkButton、または ImageButton が明示的に追加されたかどうか、または GridView によって自動的に追加されたかどうか ([並べ替えを有効にする] が選択されている場合は各列の上部にある LinkButtons、ページングを有効にする] が選択されている場合はページング インターフェイスの LinkButtons など) に対して発生します。
そのため、ユーザーが [追加] ボタンをクリックして応答するには、GridView の RowCommand
イベントのイベント ハンドラーを作成する必要があります。 このイベントは、GridView の Button、LinkButton、または ImageButton がクリックされるたびに発生するため、イベント ハンドラーに渡されたプロパティが [追加] ボタン ( [挿入] ) の値にCommandName
マップされる場合CommandName
にのみ、挿入ロジックを続行することが重要です。 さらに、検証コントロールが有効なデータを報告する場合にのみ続行する必要があります。 これに対応するには、次のコードを使用して、イベントの RowCommand
イベント ハンドラーを作成します。
protected void Products_RowCommand(object sender, GridViewCommandEventArgs e)
{
// Insert data if the CommandName == "Insert"
// and the validation controls indicate valid data...
if (e.CommandName == "Insert" && Page.IsValid)
{
// TODO: Insert new record...
}
}
注意
イベント ハンドラーがなぜプロパティのチェックを気にするのか疑問に Page.IsValid
思うかもしれません。 結局のところ、挿入インターフェイスに無効なデータが指定されている場合、ポストバックは抑制されませんか? ユーザーが JavaScript を無効にしていないか、クライアント側の検証ロジックを回避する手順を実行している限り、この前提は正しいです。 つまり、クライアント側の検証に厳密に依存してはいけません。データを操作する前に、サーバー側の有効性のチェックを常に実行する必要があります。
手順 1 では、ProductsDataSource
ObjectDataSource を作成して、そのInsert()
メソッドがクラスの メソッドAddProduct
にProductsBLL
マップされるようにしました。 新しいレコードをテーブルに Products
挿入するには、ObjectDataSource の Insert()
メソッドを呼び出すだけです。
protected void Products_RowCommand(object sender, GridViewCommandEventArgs e)
{
// Insert data if the CommandName == "Insert"
// and the validation controls indicate valid data...
if (e.CommandName == "Insert" && Page.IsValid)
{
// Insert new record
ProductsDataSource.Insert();
}
}
メソッドがInsert()
呼び出されたので、残っているのは、挿入インターフェイスからクラスの AddProduct
メソッドに渡されるパラメーターに値をProductsBLL
コピーすることです。 「 挿入、更新、削除に関連するイベントの確認 」チュートリアルで説明したように、これは ObjectDataSource の Inserting
イベントを使用して実現できます。 イベントでは、GridView の Inserting
フッター行から Products
コントロールをプログラムで参照し、その値をコレクションに e.InputParameters
割り当てる必要があります。 ユーザーが TextBox を空白のままにするなど、値を ReorderLevel
省略する場合は、データベースに挿入される値を にする NULL
必要があります。 メソッドは AddProducts
null 許容データベース フィールドに対して null 許容型を受け入れるため、単に null 許容型を使用し、ユーザー入力を省略した場合は 値を に null
設定します。
protected void ProductsDataSource_Inserting
(object sender, ObjectDataSourceMethodEventArgs e)
{
// Programmatically reference Web controls in the inserting interface...
TextBox NewProductName =
(TextBox)Products.FooterRow.FindControl("NewProductName");
DropDownList NewCategoryID =
(DropDownList)Products.FooterRow.FindControl("NewCategoryID");
DropDownList NewSupplierID =
(DropDownList)Products.FooterRow.FindControl("NewSupplierID");
TextBox NewQuantityPerUnit =
(TextBox)Products.FooterRow.FindControl("NewQuantityPerUnit");
TextBox NewUnitPrice =
(TextBox)Products.FooterRow.FindControl("NewUnitPrice");
TextBox NewUnitsInStock =
(TextBox)Products.FooterRow.FindControl("NewUnitsInStock");
TextBox NewUnitsOnOrder =
(TextBox)Products.FooterRow.FindControl("NewUnitsOnOrder");
TextBox NewReorderLevel =
(TextBox)Products.FooterRow.FindControl("NewReorderLevel");
CheckBox NewDiscontinued =
(CheckBox)Products.FooterRow.FindControl("NewDiscontinued");
// Set the ObjectDataSource's InsertParameters values...
e.InputParameters["productName"] = NewProductName.Text;
e.InputParameters["supplierID"] =
Convert.ToInt32(NewSupplierID.SelectedValue);
e.InputParameters["categoryID"] =
Convert.ToInt32(NewCategoryID.SelectedValue);
string quantityPerUnit = null;
if (!string.IsNullOrEmpty(NewQuantityPerUnit.Text))
quantityPerUnit = NewQuantityPerUnit.Text;
e.InputParameters["quantityPerUnit"] = quantityPerUnit;
decimal? unitPrice = null;
if (!string.IsNullOrEmpty(NewUnitPrice.Text))
unitPrice = Convert.ToDecimal(NewUnitPrice.Text);
e.InputParameters["unitPrice"] = unitPrice;
short? unitsInStock = null;
if (!string.IsNullOrEmpty(NewUnitsInStock.Text))
unitsInStock = Convert.ToInt16(NewUnitsInStock.Text);
e.InputParameters["unitsInStock"] = unitsInStock;
short? unitsOnOrder = null;
if (!string.IsNullOrEmpty(NewUnitsOnOrder.Text))
unitsOnOrder = Convert.ToInt16(NewUnitsOnOrder.Text);
e.InputParameters["unitsOnOrder"] = unitsOnOrder;
short? reorderLevel = null;
if (!string.IsNullOrEmpty(NewReorderLevel.Text))
reorderLevel = Convert.ToInt16(NewReorderLevel.Text);
e.InputParameters["reorderLevel"] = reorderLevel;
e.InputParameters["discontinued"] = NewDiscontinued.Checked;
}
イベント ハンドラーが Inserting
完了したら、GridView のフッター行を Products
使用してデータベース テーブルに新しいレコードを追加できます。 先に進み、いくつかの新製品を追加してみてください。
追加操作の拡張とカスタマイズ
現在、[追加] ボタンをクリックすると、データベース テーブルに新しいレコードが追加されますが、レコードが正常に追加されたことを示す視覚的なフィードバックは提供されません。 ラベル Web コントロールまたはクライアント側のアラート ボックスは、挿入が正常に完了したことをユーザーに通知するのが理想的です。 これは読者の演習として残しておきます。
このチュートリアルで使用する GridView は、リストされている製品に並べ替え順序を適用せず、エンド ユーザーがデータを並べ替えることもできます。 その結果、レコードは主キー フィールドによってデータベース内にあるように並べ替えられます。 各新しいレコードの値は ProductID
最後のレコードより大きいため、新しい製品が追加されるたびにグリッドの末尾に取り付けられます。 そのため、新しいレコードを追加した後、GridView の最後のページにユーザーを自動的に送信することができます。 これを実現するには、イベント ハンドラーで RowCommand
の呼び出しの後に次のコード行をProductsDataSource.Insert()
追加して、データを GridView にバインドした後にユーザーを最後のページに送信する必要があることを示します。
// Indicate that the user needs to be sent to the last page
SendUserToLastPage = true;
SendUserToLastPage
は、最初に 値 が割り当てられるページ レベルの false
ブール型変数です。 GridView の DataBound
イベント ハンドラーで、 が false の場合 SendUserToLastPage
、 プロパティが更新され、 PageIndex
ユーザーが最後のページに送信されます。
protected void Products_DataBound(object sender, EventArgs e)
{
// Send user to last page of data, if needed
if (SendUserToLastPage)
Products.PageIndex = Products.PageCount - 1;
}
イベント ハンドラーではなく、イベント ハンドラーで DataBound
プロパティが設定されるRowCommand
理由PageIndex
は、イベント ハンドラーが起動したときにRowCommand
、データベース テーブルに新しいレコードProducts
をまだ追加していないためです。 したがって、イベント ハンドラーでは RowCommand
、最後のページ インデックス (PageCount - 1
) は、新しい製品が追加される 前 の最後のページ インデックスを表します。 追加される製品の大部分では、新しい製品を追加した後の最後のページ インデックスは同じです。 ただし、追加された製品が新しい最後のページ インデックスになると、イベント ハンドラーで RowCommand
をPageIndex
誤って更新すると、新しい最後のページ インデックスではなく、最後のページ (新しい製品を追加する前の最後のページ インデックス) の 2 番目から最後のページに移動します。 DataBound
イベント ハンドラーは、新しい製品が追加され、データがグリッドにリバウンドした後に発生するため、 プロパティをPageIndex
設定することで、正しい最後のページ インデックスが取得されていることがわかっています。
最後に、このチュートリアルで使用される GridView は、新しい製品を追加するために収集する必要があるフィールドの数が非常に広いためです。 この幅のため、DetailsView の垂直方向のレイアウトが推奨される場合があります。 GridView の全体的な幅は、少ない入力を収集することで削減できます。 新しい製品を追加するときに、、UnitsInStock
、および ReorderLevel
の各フィールドを収集UnitsOnOrder
する必要がない場合は、これらのフィールドを GridView から削除できます。
収集されたデータを調整するには、次の 2 つの方法のいずれかを使用します。
- 、、および
ReorderLevel
フィールドのAddProduct
値を想定する メソッドをUnitsOnOrder
UnitsInStock
引き続き使用します。 イベント ハンドラーでInserting
、挿入インターフェイスから削除されたこれらの入力に使用する、ハードコーディングされた既定値を指定します。 - 、、および
ReorderLevel
フィールドの入力をAddProduct
ProductsBLL
受け入れない メソッドの新しいオーバーロードを クラスにUnitsOnOrder
UnitsInStock
作成します。 次に、ASP.NET ページで、この新しいオーバーロードを使用するように ObjectDataSource を構成します。
どちらのオプションも同様に機能します。 過去のチュートリアルでは、後者のオプションを使用して、 クラスの UpdateProduct
メソッドに対して複数のオーバーロードをProductsBLL
作成しました。
まとめ
GridView には DetailsView と FormView に含まれる組み込みの挿入機能がありませんが、少しの労力で挿入インターフェイスをフッター行に追加できます。 GridView でフッター行を表示するには、そのプロパティを ShowFooter
に true
設定するだけです。 フッター行の内容は、フィールドを TemplateField に変換し、挿入インターフェイス FooterTemplate
を に追加することで、フィールドごとにカスタマイズできます。 このチュートリアルで説明したように、 には Buttons FooterTemplate
、TextBoxes、DropDownLists、CheckBoxes、データ ドリブン Web コントロール (DropDownLists など) を設定するためのデータ ソース コントロール、検証コントロールを含めることができます。 ユーザーの入力を収集するためのコントロールと共に、ボタンの追加、リンク ボタン、または ImageButton が必要です。
[追加] ボタンをクリックすると、ObjectDataSource メソッド Insert()
が呼び出され、挿入ワークフローが開始されます。 その後、ObjectDataSource は、構成された insert メソッド (このチュートリアルでは ProductsBLL
クラス s AddProduct
メソッド) を呼び出します。 Insert メソッドが呼び出される前に、GridView の挿入インターフェイスから ObjectDataSource の InsertParameters
コレクションに値をコピーする必要があります。 これは、ObjectDataSource Inserting
のイベント ハンドラーに挿入インターフェイス Web コントロールをプログラムで参照することで実現できます。
このチュートリアルでは、GridView の外観を強化するための手法について説明します。 次のチュートリアル セットでは、画像、PDF、Word ドキュメントなどのバイナリ データとデータ Web コントロールを操作する方法について説明します。
幸せなプログラミング!
著者について
7 冊の ASP/ASP.NET 書籍の著者であり、 4GuysFromRolla.com の創設者である Scott Mitchell は、1998 年から Microsoft Web テクノロジと協力しています。 Scott は独立したコンサルタント、トレーナー、ライターとして働いています。 彼の最新の本は サムズ・ティーチ・自分自身 ASP.NET 24時間で2.0です。 にアクセスmitchell@4GuysFromRolla.comすることも、ブログを介して アクセスすることもできます。これは でhttp://ScottOnWriting.NET確認できます。
特別な感謝
このチュートリアル シリーズは、多くの役立つ校閲者によってレビューされました。 このチュートリアルのリード レビュー担当者は、ベルナデット リーでした。 今後の MSDN 記事の確認に関心がありますか? その場合は、 に行mitchell@4GuysFromRolla.comをドロップしてください。
フィードバック
https://aka.ms/ContentUserFeedback」を参照してください。
以下は間もなく提供いたします。2024 年を通じて、コンテンツのフィードバック メカニズムとして GitHub の issue を段階的に廃止し、新しいフィードバック システムに置き換えます。 詳細については、「フィードバックの送信と表示