GridView のフッターから新しいレコードを挿入する (VB)

作成者: Scott Mitchell

PDF のダウンロード

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.aspxEnhancedGridView開き、GridView をツールボックスからDesignerにドラッグし、GridView の ID プロパティを にProducts設定します。 次に、GridView のスマート タグを使用して、 という名前 ProductsDataSourceの新しい ObjectDataSource にバインドします。

ProductsDataSource という名前の新しい ObjectDataSource を作成する

図 2: 名前付きの ProductsDataSource 新しい ObjectDataSource を作成する (クリックするとフルサイズの画像が表示されます)

クラス s GetProducts() メソッドを使用して製品情報をProductsBLL取得するように ObjectDataSource を構成します。 このチュートリアルでは、挿入機能の追加に重点を置き、編集と削除について心配しないようにします。 したがって、INSERT タブのドロップダウン リストが に AddProduct() 設定されていること、および UPDATE タブと DELETE タブのドロップダウン リストが (None) に設定されていることを確認します。

AddProduct メソッドを ObjectDataSource s Insert() メソッドにマップする

図 3: メソッドを AddProduct ObjectDataSource の Insert() メソッドにマップする (クリックするとフルサイズの画像が表示されます)

[UPDATE] タブと [DELETE] タブ Drop-Down Lists を [(なし)] に設定します

図 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>

すべての製品データ フィールドが Paged GridView に表示される

図 5: すべての製品データ フィールドが Paged GridView に表示される (フルサイズの画像を表示する をクリックします)

GridView には、ヘッダー行とデータ行に加えて、フッター行が含まれます。 ヘッダー行とフッター行は、GridView ShowHeaderShowFooter の と プロパティの値に応じて表示されます。 フッター行を表示するには、 プロパティを ShowFooterTrue設定します。 図 6 に示すように、 プロパティを ShowFooter に設定すると True 、フッター行がグリッドに追加されます。

フッター行を表示するには、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 のフッターの概要情報の表示 に関するチュートリアルを参照して、更新を行います。

プロパティを にShowFooterTrue設定した後、しばらくしてブラウザーで出力を表示します。 現在、フッター行にはテキストや Web コントロールは含まれません。 手順 3 では、適切な挿入インターフェイスが含まれるように、各 GridView フィールドのフッターを変更します。

空のフッター行がページング インターフェイス コントロールの上に表示される

図 7: ページング インターフェイス コントロールの上に空のフッター行が表示されます (フルサイズの画像を表示する をクリックします)。

GridView コントロールのチュートリアルの TemplateFields の使用に関するチュートリアルでは、TemplateFields (BoundFields や CheckBoxFields ではなく) を使用して、特定の GridView 列の表示を大幅にカスタマイズする方法について説明しました。「データ変更インターフェイスのカスタマイズ」で、TemplateFields を使用して GridView の編集インターフェイスをカスタマイズする方法について説明しました。 TemplateField は、特定の種類の行に使用されるマークアップ、Web コントロール、およびデータバインド構文の組み合わせを定義する多数のテンプレートで構成されていることを思い出してください。 たとえば、 は ItemTemplate読み取り専用行に使用されるテンプレートを指定し EditItemTemplate 、 では編集可能な行のテンプレートを定義します。

EditItemTemplateに加えてItemTemplate、TemplateField にはフッター行の内容を指定する も含まれていますFooterTemplate。 したがって、 にインターフェイスを挿入する各フィールドに必要な Web コントロールを FooterTemplate追加できます。 まず、GridView 内のすべてのフィールドを TemplateFields に変換します。 これを行うには、GridView のスマート タグの [列の編集] リンクをクリックし、左下隅にある各フィールドを選択し、[このフィールドを TemplateField に変換する] リンクをクリックします。

各フィールドを 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 コントロールを含む ItemTemplateEditItemTemplate 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に適切なコントロールをドラッグします。

各フィールドの FooterTemplate に適切な挿入インターフェイスを追加する

図 9: 各フィールドに適切な挿入インターフェイスを追加する (フルサイズのFooterTemplate画像を表示する をクリックします)

次の箇条書きでは、追加する挿入インターフェイスを指定して、GridView フィールドを列挙します。

  • ProductID なし。
  • ProductName TextBox を追加し、 を IDNewProductName設定します。 RequiredFieldValidator コントロールを追加して、ユーザーが新しい製品名の値を入力するようにします。
  • SupplierID なし。
  • CategoryID なし。
  • QuantityPerUnit TextBox を追加し、 を IDNewQuantityPerUnit設定します。
  • 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 を追加し、 を IDNewDiscontinued設定します。
  • CategoryName DropDownList を追加し、 を ID に設定します NewCategoryID。 それを という名前CategoriesDataSourceの新しい ObjectDataSource にバインドし、クラス s GetCategories() メソッドをCategoriesBLL使用するように構成します。 データ フィールドを値として使用して、DropDownList ListItem にデータ フィールドをCategoryID表示CategoryNameしてもらいます。
  • SupplierName DropDownList を追加し、 を ID に設定します NewSupplierID。 それを という名前SuppliersDataSourceの新しい ObjectDataSource にバインドし、クラス s GetSuppliers() メソッドをSuppliersBLL使用するように構成します。 データ フィールドを値として使用して、DropDownList ListItem にデータ フィールドをSupplierID表示CompanyNameしてもらいます。

検証コントロールごとに、 プロパティを ForeColor クリアして、CSS クラスの白い前景色が既定の赤の代わりに使用されるように FooterStyle します。 また、 ErrorMessage 詳細な説明には プロパティを使用しますが、 プロパティを Text アスタリスクに設定します。 入力規則コントロールのテキストによって挿入インターフェイスが 2 行に折り返されないようにするには、検証コントロールを使用する s ごとに FooterTemplate s Wrap プロパティを false に設定FooterStyleします。 最後に、GridView の下に ValidationSummary コントロールを追加し、その ShowMessageBox プロパティを に True 、そのプロパティを ShowSummary に設定します False

新しい製品を追加するときは、 と SupplierIDCategoryID指定する必要があります。 この情報は、 フィールドと SupplierName フィールドのフッター セルの DropDownLists によってCategoryNameキャプチャされます。 グリッドのデータ行では、ユーザーが ID 値ではなくカテゴリ名とサプライヤー名を表示することに関心がある可能性が高いため、 と SupplierID TemplateFields ではなくCategoryID、これらのフィールドを使用することを選択しました。 と SupplierIDCategoryID値は、 および SupplierName フィールドの挿入インターフェイスでCategoryNameキャプチャされるようになったため、GridView から および SupplierID TemplateFields を削除CategoryIDできます。

同様に、 ProductID は新しい製品を追加するときに使用されないため ProductID 、TemplateField も削除できます。 ただし、グリッド内のフィールドはそのまま ProductID にします。 挿入インターフェイスを構成する TextBoxes、DropDownLists、CheckBoxes、および検証コントロールに加えて、[追加] ボタンも必要です。このボタンをクリックすると、新しい製品をデータベースに追加するロジックが実行されます。 手順 4 では、TemplateField の FooterTemplate挿入インターフェイスに [追加] ボタンをProductID含めます。

さまざまな GridView フィールドの外観を自由に改善してください。 たとえば、値を通貨として書式設定UnitPriceし、、UnitsOnOrder、および ReorderLevel フィールドをUnitsInStock右揃えにして、TemplateFields のHeaderText値を更新することができます。

にインターフェイス FooterTemplate を挿入し、、、および TemplateFields を削除 SupplierIDし、TemplateFields の書式設定と CategoryID 配置によってグリッドの美しさを向上させるスルーを作成した後、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 では、フッターのデータを使用して新しいレコードを挿入する方法を示します。

GridView フッターには、新しいレコードを追加するためのインターフェイスが用意されています

図 10: GridView フッターは、新しいレコードを追加するためのインターフェイスを提供します (フルサイズの画像を表示する をクリックします)。

手順 4: 挿入インターフェイスに追加ボタンを含める

フッター行の挿入インターフェイスには現在、ユーザーが新製品の情報の入力を完了したことを示す手段がないため、挿入インターフェイスのどこかに [追加] ボタンを含める必要があります。 これは、既存 FooterTemplate の のいずれかに配置することも、この目的のためにグリッドに新しい列を追加することもできます。 このチュートリアルでは、TemplateField の FooterTemplateに [追加] ボタンをProductID配置します。

Designerから、GridView のスマート タグの [テンプレートの編集] リンクをクリックし、ドロップダウン リストからフィールドをFooterTemplate選択ProductIDします。 ボタン Web コントロール (または必要に応じて LinkButton または ImageButton) をテンプレートに追加し、その ID を に AddProduct設定し、その CommandName ID を Insert に、プロパティを Text Add に設定します (図 11 を参照)。

ProductID TemplateFields FooterTemplate に [追加] ボタンを配置する

図 11: TemplateFields に [追加] ボタンをProductID配置する (クリックするとフルサイズのFooterTemplate画像が表示されます)

[追加] ボタンを含めたら、ブラウザーでページをテストします。 挿入インターフェイスで無効なデータを含む [追加] ボタンをクリックすると、ポストバックがショートし、ValidationSummary コントロールが無効なデータを示します (図 12 を参照)。 適切なデータを入力すると、[追加] ボタンをクリックするとポストバックが発生します。 ただし、データベースにレコードは追加されません。 実際に挿入を実行するには、少しコードを記述する必要があります。

挿入インターフェイスに無効なデータがある場合、ボタンのポストバックがショートする

図 12: 挿入インターフェイスに無効なデータがある場合、[ボタンのポストバックの追加] がショート サーキット (フルサイズの画像を表示する をクリックします)

注意

挿入インターフェイスの検証コントロールが検証グループに割り当てられません。 挿入インターフェイスがページ上の検証コントロールの唯一のセットである限り、これは正常に動作します。 ただし、ページ上に他の検証コントロール (グリッドの編集インターフェイスの検証コントロールなど) がある場合は、挿入インターフェイスの検証コントロールと [ボタンのプロパティの ValidationGroup 追加] に同じ値を割り当てて、これらのコントロールを特定の検証グループに関連付ける必要があります。 ページ 上の検証コントロールとボタンを検証グループに パーティション分割する方法の詳細については、「ASP.NET 2.0 での検証コントロールの分離」を参照してください。

手順 5: テーブルに新しいレコードを挿入するProducts

GridView の組み込みの編集機能を利用すると、GridView は更新を実行するために必要なすべての作業を自動的に処理します。 特に、[更新] ボタンをクリックすると、編集インターフェイスから入力した値が ObjectDataSource のコレクション内の UpdateParameters パラメーターにコピーされ、ObjectDataSource の Update() メソッドを呼び出して更新が開始されます。 GridView には挿入用のこのような組み込み機能がないため、ObjectDataSource の メソッドを呼び出し、挿入インターフェイスから ObjectDataSource InsertParametersInsert()コレクションに値をコピーするコードを実装する必要があります。

この挿入ロジックは、[追加] ボタンがクリックされた後に実行する必要があります。 「GridView でのボタンの追加と応答」チュートリアルで説明したように、GridView の Button、LinkButton、または ImageButton がクリックされるたびに、GridView のRowCommandイベントはポストバック時に発生します。 このイベントは、フッター行の [追加] ボタンなど、Button、LinkButton、または ImageButton が明示的に追加されたか、GridView によって自動的に追加されたかどうか ([並べ替えを有効にする] が選択されている場合は各列の上部にある LinkButtons、ページング インターフェイスで [ページングを有効にする] が選択されている場合は LinkButtons など) に対して発生します。

そのため、[追加] ボタンをクリックしたユーザーに応答するには、GridView の RowCommand イベントのイベント ハンドラーを作成する必要があります。 このイベントは、GridView の Button、LinkButton、または ImageButton がクリックされるたびに発生するため、イベント ハンドラーに渡されたプロパティが Add ボタン (Insert) の値にCommandNameマップされる場合CommandNameにのみ、挿入ロジックを続行することが重要です。 さらに、検証コントロールが有効なデータを報告する場合にのみ、続行する必要があります。 これに対応するには、次のコードを使用して、 イベントの RowCommand イベント ハンドラーを作成します。

Protected Sub Products_RowCommand(sender As Object, e As GridViewCommandEventArgs) _
    Handles Products.RowCommand
    
    ' Insert data if the CommandName == "Insert" 
    ' and the validation controls indicate valid data...
    If e.CommandName = "Insert" AndAlso Page.IsValid Then
        ' TODO: Insert new record...
    End If
End Sub

注意

イベント ハンドラーがプロパティのチェックを煩わしている理由を疑問に Page.IsValid 思うかもしれません。 結局のところ、挿入インターフェイスに無効なデータが指定されている場合、ポストバックは抑制されませんか? ユーザーが JavaScript を無効にしていないか、クライアント側の検証ロジックを回避する手順を実行している限り、この想定は正しいです。 つまり、クライアント側の検証に厳密に依存してはいけません。データを操作する前に、サーバー側の有効性のチェックを常に実行する必要があります。

手順 1 では、そのメソッドが ProductsDataSource クラスの AddProduct メソッドにマップされるように Insert() ObjectDataSource をProductsBLL作成しました。 新しいレコードをテーブルに Products 挿入するには、ObjectDataSource の Insert() メソッドを呼び出すだけです。

Protected Sub Products_RowCommand(sender As Object, e As GridViewCommandEventArgs) _
    Handles Products.RowCommand
    
    ' Insert data if the CommandName == "Insert" 
    ' and the validation controls indicate valid data...
    If e.CommandName = "Insert" AndAlso Page.IsValid Then
        ' Insert new record
        ProductsDataSource.Insert()
    End If
End Sub

メソッドがInsert()呼び出されたので、残っているのは、挿入インターフェイスからクラスの AddProduct メソッドに渡されるパラメーターに値をProductsBLLコピーすることにあります。 「 挿入、更新、および削除に関連するイベントの確認 」チュートリアルで説明したように、これは ObjectDataSource の Inserting イベントを使用して実現できます。 イベントでは、GridView の Inserting フッター行からコントロールを Products プログラムで参照し、その値をコレクションに e.InputParameters 割り当てる必要があります。 ユーザーが TextBox を空白のままにするなど、値を省略する ReorderLevel 場合は、データベースに挿入される値を に NULL指定する必要があります。 メソッドは AddProducts null 許容データベース フィールドに対して null 許容型を受け入れるので、単に null 許容型を使用し、ユーザー入力を省略した場合にその値を に Nothing 設定します。

Protected Sub ProductsDataSource_Inserting _
    (sender As Object, e As .ObjectDataSourceMethodEventArgs) _
    Handles ProductsDataSource.Inserting
    
    ' Programmatically reference Web controls in the inserting interface...
    Dim NewProductName As TextBox = _
        Products.FooterRow.FindControl("NewProductName")
    Dim NewCategoryID As DropDownList = _
        Products.FooterRow.FindControl("NewCategoryID")
    Dim NewSupplierID As DropDownList = _
        Products.FooterRow.FindControl("NewSupplierID")
    Dim NewQuantityPerUnit As TextBox = _
        Products.FooterRow.FindControl("NewQuantityPerUnit")
    Dim NewUnitPrice As TextBox = _
        Products.FooterRow.FindControl("NewUnitPrice")
    Dim NewUnitsInStock As TextBox = _
        Products.FooterRow.FindControl("NewUnitsInStock")
    Dim NewUnitsOnOrder As TextBox = _
        Products.FooterRow.FindControl("NewUnitsOnOrder")
    Dim NewReorderLevel As TextBox = _
        Products.FooterRow.FindControl("NewReorderLevel")
    Dim NewDiscontinued As 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)
    Dim quantityPerUnit As String = Nothing
    If Not String.IsNullOrEmpty(NewQuantityPerUnit.Text) Then
        quantityPerUnit = NewQuantityPerUnit.Text
    End If
    e.InputParameters("quantityPerUnit") = quantityPerUnit
    Dim unitPrice As Nullable(Of Decimal) = Nothing
    If Not String.IsNullOrEmpty(NewUnitPrice.Text) Then
        unitPrice = Convert.ToDecimal(NewUnitPrice.Text)
    End If
    e.InputParameters("unitPrice") = unitPrice
    Dim unitsInStock As Nullable(Of Short) = Nothing
    If Not String.IsNullOrEmpty(NewUnitsInStock.Text) Then
        unitsInStock = Convert.ToInt16(NewUnitsInStock.Text)
    End If
    e.InputParameters("unitsInStock") = unitsInStock
    Dim unitsOnOrder As Nullable(Of Short) = Nothing
    If Not String.IsNullOrEmpty(NewUnitsOnOrder.Text) Then
        unitsOnOrder = Convert.ToInt16(NewUnitsOnOrder.Text)
    End If
    e.InputParameters("unitsOnOrder") = unitsOnOrder
    Dim reorderLevel As Nullable(Of Short) = Nothing
    If Not String.IsNullOrEmpty(NewReorderLevel.Text) Then
        reorderLevel = Convert.ToInt16(NewReorderLevel.Text)
    End If
    e.InputParameters("reorderLevel") = reorderLevel
    e.InputParameters("discontinued") = NewDiscontinued.Checked
End Sub

イベント ハンドラーが 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 Sub Products_DataBound(sender As Object, e As EventArgs) _
    Handles Products.DataBound
    
    ' Send user to last page of data, if needed
    If SendUserToLastPage Then
        Products.PageIndex = Products.PageCount - 1
    End If
End Sub

イベント ハンドラーで DataBound プロパティが設定されているRowCommand理由PageIndexは、イベント ハンドラーが起動したときにRowCommand、新しいレコードをデータベース テーブルにProductsまだ追加していないためです。 したがって、イベント ハンドラーでは RowCommand 、最後のページ インデックス (PageCount - 1) は、新しい製品が追加される の最後のページ インデックスを表します。 追加される製品の大部分では、新しい製品を追加した後の最後のページ インデックスは同じです。 ただし、追加された製品で新しい最後のページ インデックスが作成されると、イベント ハンドラーで RowCommandPageIndex誤って更新すると、新しい最後のページ インデックスではなく、最後のページ (新しい製品を追加する前の最後のページ インデックス) の 2 番目から最後のページに移動します。 DataBoundイベント ハンドラーは、新しい製品が追加され、データがグリッドにリバウンドした後に発生するため、 プロパティをPageIndex設定することで、正しい最後のページ インデックスが取得されていることがわかります。

最後に、このチュートリアルで使用される GridView は、新しい製品を追加するために収集する必要があるフィールドの数が原因で非常に広いです。 この幅のため、DetailsView の垂直レイアウトが推奨される場合があります。 GridView の全体的な幅は、より少ない入力を収集することで減らすことができます。 新しい製品を追加するときに、、UnitsInStock、および ReorderLevel の各フィールドを収集UnitsOnOrderする必要はありません。その場合、これらのフィールドは GridView から削除される可能性があります。

収集されたデータを調整するには、次の 2 つの方法のいずれかを使用します。

  • 、、および ReorderLevel フィールドのAddProduct値を想定する メソッドをUnitsOnOrderUnitsInStock引き続き使用します。 イベント ハンドラーで Inserting 、挿入インターフェイスから削除されたこれらの入力に使用する、ハードコーディングされた既定値を指定します。
  • 、、および ReorderLevel フィールドの入力をAddProductProductsBLL受け入れない メソッドの新しいオーバーロードを クラスにUnitsOnOrderUnitsInStock作成します。 次に、ASP.NET ページで、この新しいオーバーロードを使用するように ObjectDataSource を構成します。

どちらのオプションも同様に機能します。 過去のチュートリアルでは、後者のオプションを使用して、 クラスの UpdateProduct メソッドに対して複数のオーバーロードをProductsBLL作成しました。

まとめ

GridView には DetailsView と FormView に含まれる組み込みの挿入機能がありませんが、少しの労力で挿入インターフェイスをフッター行に追加できます。 GridView でフッター行を表示するには、そのプロパティを ShowFooterTrue設定するだけです。 フッター行の内容は、フィールドを 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をドロップしてください。