DataList のデータの編集と削除の概要 (C#)

作成者: Scott Mitchell

PDF のダウンロード

DataList には組み込みの編集および削除機能はありませんが、このチュートリアルでは、基になるデータの編集と削除をサポートする DataList を作成する方法について説明します。

はじめに

データの挿入、更新、および削除の概要に関するチュートリアルでは、アプリケーション アーキテクチャ、ObjectDataSource、GridView、DetailsView、FormView コントロールを使用してデータを挿入、更新、削除する方法について説明しました。 ObjectDataSource とこれら 3 つのデータ Web コントロールでは、単純なデータ変更インターフェイスの実装は簡単であり、スマート タグからチェック ボックスをオンにするだけでした。 コードを記述する必要はありませんでした。

残念ながら、DataList には、GridView コントロールに固有の組み込みの編集機能と削除機能がありません。 この不足している機能の一部は、DataList が宣言型データ ソース コントロールとコードフリーのデータ変更ページが使用できなかった以前のバージョンの ASP.NET のレリックであることが原因です。 ASP.NET 2.0 の DataList には、GridView と同じすぐに使用できるデータ変更機能はありませんが、ASP.NET 1.x の手法を使用してそのような機能を含めることができます。 この方法には少しコードが必要ですが、このチュートリアルで説明するように、DataList には、このプロセスを支援するためにいくつかのイベントとプロパティが用意されています。

このチュートリアルでは、基になるデータの編集と削除をサポートする DataList を作成する方法について説明します。 今後のチュートリアルでは、入力フィールドの検証、データ アクセスまたはビジネス ロジック レイヤーから発生した例外の適切な処理など、より高度な編集と削除のシナリオについて説明します。

Note

DataList と同様に、Repeater コントロールには、挿入、更新、または削除のための既定の機能がありません。 そのような機能を追加することはできますが、DataList には、このような機能の追加を簡略化する Repeater にないプロパティとイベントが含まれています。 したがって、このチュートリアルと今後の編集と削除については、DataList に重点を置きます。

手順 1: チュートリアル Web ページの編集と削除の作成

DataList からデータを更新および削除する方法を調べる前に、まず、このチュートリアルと次のいくつかのページに必要な ASP.NET ページを Web サイト プロジェクトに作成してみましょう。 まず、EditDeleteDataList という名前の新しいフォルダーを追加します。 次に、次の ASP.NET ページをそのフォルダーに追加し、各ページを Site.master マスター ページに関連付けます。

  • Default.aspx
  • Basics.aspx
  • BatchUpdate.aspx
  • ErrorHandling.aspx
  • UIValidation.aspx
  • CustomizedUI.aspx
  • OptimisticConcurrency.aspx
  • ConfirmationOnDelete.aspx
  • UserLevelAccess.aspx

チュートリアルの ASP.NET ページを追加する

図 1: チュートリアルの ASP.NET ページを追加する

他のフォルダーと同様に、EditDeleteDataList フォルダーの Default.aspx のセクションにチュートリアルが一覧表示されます。 SectionLevelTutorialListing.ascx ユーザー コントロールではこの機能が提供されていることを思い出してください。 そのため、このユーザー コントロールをソリューション エクスプローラーからページのデザイン ビューにドラッグして Default.aspx に追加します。

SectionLevelTutorialListing.ascx ユーザー コントロールを Default.aspx に追加する

図 2: SectionLevelTutorialListing.ascx ユーザー コントロールを Default.aspx に追加する (クリックするとフルサイズの画像が表示されます)

最後に、このページをエントリとして Web.sitemap ファイルに追加します。 具体的には、DataList と Repeater <siteMapNode> を使用してマスター/詳細レポートの後に次のマークアップを追加します。

<siteMapNode
    title="Editing and Deleting with the DataList"
    description="Samples of Reports that Provide Editing and Deleting Capabilities"
    url="~/EditDeleteDataList/Default.aspx" >
    <siteMapNode
        title="Basics"
        description="Examines the basics of editing and deleting with the
                     DataList control."
        url="~/EditDeleteDataList/Basics.aspx" />
    <siteMapNode
        title="Batch Update"
        description="Examines how to update multiple records at once in a
                     fully-editable DataList."
        url="~/EditDeleteDataList/BatchUpdate.aspx" />
    <siteMapNode
        title="Error Handling"
        description="Learn how to gracefully handle exceptions raised during the
                     data modification workflow."
        url="~/EditDeleteDataList/ErrorHandling.aspx" />
    <siteMapNode
        title="Adding Data Entry Validation"
        description="Help prevent data entry errors by providing validation."
        url="~/EditDeleteDataList/UIValidation.aspx" />
    <siteMapNode
        title="Customize the User Interface"
        description="Customize the editing user interfaces."
        url="~/EditDeleteDataList/CustomizedUI.aspx" />
    <siteMapNode
        title="Optimistic Concurrency"
        description="Learn how to help prevent simultaneous users from
                     overwritting one another s changes."
        url="~/EditDeleteDataList/OptimisticConcurrency.aspx" />
    <siteMapNode
        title="Confirm On Delete"
        description="Prompt a user for confirmation when deleting a record."
        url="~/EditDeleteDataList/ConfirmationOnDelete.aspx" />
    <siteMapNode
        title="Limit Capabilities Based on User"
        description="Learn how to limit the data modification functionality
                     based on the user s role or permissions."
        url="~/EditDeleteDataList/UserLevelAccess.aspx" />
</siteMapNode>

Web.sitemap を更新した後、少し時間を取って、ブラウザーを介してチュートリアル Web サイトを表示します。 左側のメニューに、DataList の編集と削除のチュートリアル用の項目が含まれるようになりました。

サイト マップに DataList の編集と削除に関するチュートリアルのエントリが含まれるようになりました

図 3: サイト マップに DataList の編集と削除のチュートリアルのエントリが含まれるようになりました

手順 2: データの更新と削除の手法を調べる

GridView と ObjectDataSource が連携して機能するため、GridView を使用したデータの編集と削除は非常に簡単です。 挿入、更新、削除に関連するイベントの検査のチュートリアルで説明したように、行の [更新] ボタンをクリックすると、GridView では、双方向データ バインドを使用したフィールドを ObjectDataSource の UpdateParameters コレクションに自動的に割り当て、その ObjectDataSource の Update() メソッドを呼び出します。

残念ながら、DataList には、この組み込み機能はありません。 ユーザーの値が ObjectDataSource のパラメーターに割り当てられ、その Update() メソッドが呼び出されるようにする必要があります。 この取り組みを支援するために、DataList には次のプロパティとイベントが用意されています。

  • 更新時または削除時の DataKeyField プロパティは、DataList 内の各項目を一意に識別できる必要があります。 このプロパティを、表示されるデータの主キー フィールドに設定します。 これにより、DataList の DataKeys コレクションに、DataList 項目ごとに指定した DataKeyField 値が設定されます。
  • EditCommand イベントは、CommandName プロパティが Edit に設定されている Button、LinkButton、または ImageButton がクリックされたときに発生します。
  • CancelCommand イベントは、CommandName プロパティが Cancel に設定されている Button、LinkButton、または ImageButton がクリックされたときに発生します。
  • UpdateCommand イベントは、CommandName プロパティが Update に設定されている Button、LinkButton、または ImageButton がクリックされたときに発生します。
  • DeleteCommand イベントは、CommandName プロパティが Delete に設定されている Button、LinkButton、または ImageButton がクリックされたときに発生します。

これらのプロパティとイベントを使用して、DataList からデータを更新および削除するために使用できる 4 つの方法があります。

  1. ASP.NET 1.x の手法を使用する。DataList は ASP.NET 2.0 および ObjectDataSources より前に存在し、プログラムによる方法でデータを完全に更新および削除できました。 この手法では ObjectDataSource が完全に削除され、データをビジネス ロジック レイヤーから DataList に直接バインドする必要があります。これは、表示するデータを取得するときと、レコードを更新または削除する場合の両方です。
  2. ページで単一の ObjectDataSource コントロールを使用して、選択、更新、および削除を行う。DataList には GridView にはある編集および削除機能がありませんが、自分で追加できないわけではありません。 この方法では、GridView の例と同様に ObjectDataSource を使用しますが、ObjectDataSource のパラメーターを設定してその Update() メソッドを呼び出す DataList の UpdateCommand イベントのイベント ハンドラーを作成する必要があります。
  3. 選択に ObjectDataSource コントロールを使用するが、更新と削除は BLL に対して直接行う。オプション 2 を使用する場合、UpdateCommand イベントに少しコードを記述し、パラメーター値を割り当てる必要があります。 代わりに、ObjectDataSource を使用して選択しますが、BLL に対して直接を更新および削除の呼び出しを行います (オプション 1 のように)。 個人的には、BLL と直接やり取りしてデータを更新すると、ObjectDataSource の UpdateParameters を割り当ててその Update() メソッドを呼び出すよりも読みやすいコードにつながると思います。
  4. 複数の ObjectDataSource を通じて宣言的方法を使用する。前の 3 つのアプローチはすべて、少しのコードを必要とします。 できるだけ多くの宣言構文を使用し続ける場合、最後のオプションは、ページに複数の ObjectDataSource を含める方法です。 最初の ObjectDataSource は、BLL からデータを取得し、DataList にバインドします。 更新の場合、別の ObjectDataSource が追加されますが、DataList の EditItemTemplate に直接追加されます。 削除のサポートを含めるには、さらに別の ObjectDataSource が ItemTemplate に必要です。 この方法では、これらの埋め込み ObjectDataSource で ControlParameters を使用して、ObjectDataSource のパラメーターをユーザー入力コントロールに宣言的にバインドします (DataList の UpdateCommand イベント ハンドラーでプログラムで指定するのではなく)。 この方法では、埋め込み ObjectDataSource の Update() または Delete() コマンドを呼び出すためのコードが少し必要ですが、他の 3 つの方法よりもはるかに少なくて済みます。 ここでの欠点は、複数の ObjectDataSource がページを乱雑にし、全体的な読みやすさを損なうことです。

これらのアプローチのいずれか 1 つだけを使用することを余儀なくされた場合は、オプション 1 を選択します。これは、最も柔軟性が高く、DataList がもともとこのパターンに対応するように設計されているためです。 DataList は、ASP.NET 2.0 データ ソース コントロールと連携するように拡張されましたが、公式の ASP.NET 2.0 データ Web コントロール (GridView、DetailsView、FormView) のすべての機能を備えているわけではありません。 ただし、オプション 2 から 4 にはメリットがないわけではありません。

このチュートリアルと今後の編集と削除のチュートリアルでは、ObjectDataSource を使用して、表示するデータを取得し、BLL への呼び出しを行ってデータを更新および削除します (オプション 3)。

手順 3: DataList の追加とその ObjectDataSource の構成

このチュートリアルでは、製品情報を一覧表示する DataList を作成し、各製品について、ユーザーが名前と価格を編集し、製品を完全に削除できる機能を提供します。 特に、ObjectDataSource を使用して表示するレコードを取得しますが、BLL と直接やり取りして更新アクションと削除アクションを実行します。 DataList に対する編集と削除機能の実装について心配する前に、まず、読み取り専用インターフェイスで製品を表示するページを取得しましょう。 前のチュートリアルでこれらの手順を調べたので、手早く進めます。

まず、EditDeleteDataList フォルダー内の Basics.aspx ページを開き、デザイン ビューから DataList をページに追加します。 次に、DataList のスマート タグから、新しい ObjectDataSource を作成します。 製品データを扱っているため、ProductsBLL クラスを使用するように構成します。 "すべての" 製品を取得するには、[SELECT] タブで GetProducts() メソッドを選択します。

ProductsBLL クラスを使用するように ObjectDataSource を構成する

図 4: クラスを使用するように ObjectDataSource を構成します ProductsBLL (フルサイズの画像を表示する をクリックします)

GetProducts() メソッドを使用して製品情報を返す

図 5: GetProducts() メソッドを使用して製品情報を返します (クリックしてフルサイズの画像を表示)

DataList は、GridView と同様に、新しいデータを挿入するために設計されていません。そのため、[INSERT] タブのドロップダウン リストから (なし) オプションを選択します。更新と削除は BLL を介してプログラムによって実行されるため、[UPDATE] と [DELETE] タブにも (なし) を選択します。

ObjectDataSource の INSERT、UPDATE、DELETE タブのドロップダウン リストが (なし) に設定されていることを確認します

図 6: ObjectDataSource の INSERT、UPDATE、DELETE タブのドロップダウン リストが (なし) に設定されていることを確認します (クリックしてフルサイズの画像を表示)

ObjectDataSource を構成したら、[完了] をクリックしてデザイナーに戻ります。 前の例で説明したように、ObjectDataSource 構成を完了すると、Visual Studio によって DropDownList 用の ItemTemplate が自動的に作成され、各データ フィールドが表示されます。 この ItemTemplate を、製品名と価格のみを表示する値に置き換えます。 また、RepeatColumns プロパティを 2 に設定します。

Note

データの挿入、更新、削除の概要のチュートリアルで説明したように、ObjectDataSource を使用してデータを変更する場合、アーキテクチャでは、ObjectDataSource の宣言型マークアップから OldValuesParameterFormatString プロパティを削除する (または既定値 {0} にリセットする) 必要があります。 ただし、このチュートリアルでは、データの取得にのみ ObjectDataSource を使用します。 したがって、ObjectDataSource の OldValuesParameterFormatString プロパティ値を変更する必要はありません (ただし、変更しても問題ありません)。

既定の DataList ItemTemplate をカスタマイズされたものに置き換えた後、ページの宣言型マークアップは次のようになります。

<asp:DataList ID="DataList1" runat="server" DataKeyField="ProductID"
    DataSourceID="ObjectDataSource1" RepeatColumns="2">
    <ItemTemplate>
        <h5>
            <asp:Label runat="server" ID="ProductNameLabel"
                Text='<%# Eval("ProductName") %>'></asp:Label>
        </h5>
        Price: <asp:Label runat="server" ID="Label1"
                    Text='<%# Eval("UnitPrice", "{0:C}") %>' />
        <br />
        <br />
    </ItemTemplate>
</asp:DataList>
<asp:ObjectDataSource ID="ObjectDataSource1" runat="server"
    SelectMethod="GetProducts" TypeName="ProductsBLL"
    OldValuesParameterFormatString="original_{0}">
</asp:ObjectDataSource>

ブラウザーを使用して進行状況を確認します。 図 7 に示すように、DataList には、各製品の製品名と単価が 2 つの列に表示されます。

製品名と価格は、2 列の DataList に表示されます

図 7: 製品名と価格が 2 列の DataList に表示されます (クリックしてフルサイズの画像を表示)

Note

DataList には、更新と削除のプロセスに必要なプロパティが多数あり、これらの値はビュー状態に格納されます。 そのため、データの編集または削除をサポートする DataList を構築する場合は、DataList のビュー状態を有効にすることが不可欠です。

編集可能な GridView、DetailsViews、FormView を作成するときに、ビュー状態を無効にできたことを、鋭い読者は思い出すかもしれません。 これは、ASP.NET 2.0 Web コントロールに "コントロールの状態" が含まれる可能性があるためです。これは、ビュー状態などのポストバック間で状態が保持されますが、必須と見なされるものです。

GridView でビュー状態を無効にすると、単純な状態情報が省略されるだけで、コントロールの状態 (編集と削除に必要な状態が含まれます) が維持されます。 DataList は、ASP.NET 1.x の時期に作成されており、コントロールの状態を利用しないため、ビュー状態を有効にする必要があります。 コントロールの状態とビュー状態の比較に関するページで、コントロールの状態の目的とビュー状態との違いについて詳しく確認してください。

手順 4: 編集ユーザー インターフェイスを追加する

GridView コントロールは、フィールドのコレクション (BoundFields、CheckBoxFields、TemplateFields など) で構成されます。 これらのフィールドは、モードに応じてレンダリングされるマークアップを調整できます。 たとえば、読み取り専用モードの場合、BoundField はデータ フィールドの値をテキストとして表示します。編集モードでは、Text プロパティにデータ フィールド値が割り当てられている TextBox Web コントロールがレンダリングされます。

一方、DataList はテンプレートを使用してその項目をレンダリングします。 読み取り専用の項目は ItemTemplate 使用してレンダリングされ、編集モードの項目は EditItemTemplate を介してレンダリングされます。 この時点で、DataList には ItemTemplate のみがあります。 項目レベルの編集機能をサポートするには、編集可能な項目に表示するマークアップを含む EditItemTemplate を追加する必要があります。 このチュートリアルでは、製品名と単価を編集するために TextBox Web コントロールを使用します。

EditItemTemplate は、宣言型またはデザイナーを使用して作成できます (DataList のスマート タグから [テンプレートの編集] オプションを選択します)。 [テンプレートの編集] オプションを使用するには、まずスマート タグの [テンプレートの編集] リンクをクリックし、ドロップダウン リストから EditItemTemplate 項目を選択します。

DataList s EditItemTemplate の使用を選択する

図 8: DataList の EditItemTemplate の使用を選びます (クリックしてフルサイズの画像を表示する)

次に、「Product name:」と「Price:」に入力し、ツールボックスからデザイナーの EditItemTemplate インターフェイスに 2 つの TextBox コントロールをドラッグします。 TextBox の ID プロパティを ProductNameUnitPrice に設定します。

製品名と価格のテキスト ボックスを追加する

図 9: 製品名と価格の TexBox を追加します (クリックしてフルサイズの画像を表示)

対応する製品データ フィールドの値を 2 つの TextBox の Text プロパティにバインドする必要があります。 図 10 に示すように、TextBox スマート タグから [DataBindings の編集] リンクをクリックし、適切なデータ フィールドを Text プロパティに関連付けます。

Note

UnitPrice データ フィールドを価格 TextBox の Text フィールドにバインドする場合は、書式設定を通貨値 ({0:C})、一般数値 ({0:N})、またはなしにできます。

ProductName および UnitPrice データ フィールドを TextBoxes の Text プロパティにバインドする

図 10: TextBox の Text プロパティに ProductNameUnitPrice データ フィールドをバインドする

図 10 の [DataBindings の編集] ダイアログ ボックスには、GridView または DetailsView の TemplateField または FormView のテンプレートを編集するときに表示される双方向データ バインド のチェック ボックスが含まれて "いない" ことに注意してください。 双方向データ バインド機能を使用すると、入力 Web コントロールに入力された値を、対応する ObjectDataSource の InsertParameters または UpdateParameters に自動的に割り当てたり、データを挿入または更新したりすることができました。 このチュートリアルの後半で説明するように、DataList は双方向データ バインドをサポートしていません。ユーザーが変更を行い、データを更新する準備ができたら、これらの TextBox の Text プロパティにプログラムでアクセスし、その値を ProductsBLL クラスの適切な UpdateProduct メソッドに渡す必要があります。

最後に、[更新] ボタンと [キャンセル] ボタンを EditItemTemplate に追加する必要があります。 マスター レコードの箇条書きと詳細 DataList を使用してマスター/詳細を表示するチュートリアルで説明したように、CommandName プロパティが設定されている Button、LinkButton、または ImageButton が Repeater または DataList 内からクリックされると、Repeater または DataList の ItemCommand イベントが発生します。 DataList の場合、CommandName プロパティが特定の値に設定されている場合は、追加のイベントも発生する可能性があります。 特別な CommandName プロパティ値には、次のようなものがあります。

  • Cancel によって CancelCommand イベントが発生する
  • Edit によって EditCommand イベントが発生する
  • Update によって UpdateCommand イベントが発生する

これらのイベントは、ItemCommand イベントに "加えて" 発生することに注意してください。

EditItemTemplate に 2 つの Button Web コントロールに追加します。1 つの CommandName は [Update] に設定され、もう 1 つは [Cancel] に設定されています。 これら 2 つの Button Web コントロールを追加すると、デザイナーは次のようになります。

[更新] ボタンと [キャンセル] ボタンが追加された DataList EditItemTemplate を示すスクリーンショット。

図 11: EditItemTemplate に更新ボタンとキャンセル ボタンを追加します (クリックしてフルサイズの画像を表示)

EditItemTemplate が完了すると、DataList の宣言型マークアップは次のようになります。

<asp:DataList ID="DataList1" runat="server" DataKeyField="ProductID"
    DataSourceID="ObjectDataSource1" RepeatColumns="2">
    <ItemTemplate>
        <h5>
            <asp:Label runat="server" ID="ProductNameLabel"
                Text='<%# Eval("ProductName") %>' />
        </h5>
        Price: <asp:Label runat="server" ID="Label1"
                    Text='<%# Eval("UnitPrice", "{0:C}") %>' />
        <br />
        <br />
    </ItemTemplate>
    <EditItemTemplate>
        Product name:
            <asp:TextBox ID="ProductName" runat="server"
                Text='<%# Eval("ProductName") %>' /><br />
        Price:
            <asp:TextBox ID="UnitPrice" runat="server"
                Text='<%# Eval("UnitPrice", "{0:C}") %>' /><br />
        <br />
        <asp:Button ID="UpdateProduct" runat="server"
            CommandName="Update" Text="Update" /> 
        <asp:Button ID="CancelUpdate" runat="server"
            CommandName="Cancel" Text="Cancel" />
    </EditItemTemplate>
</asp:DataList>

手順 5: 編集モードに入る仕組みを追加する

この時点で、DataList には EditItemTemplate によって編集インターフェイスが定義されています。ただし、現在、ユーザーが製品の情報を編集することを示す方法はありません。 クリックすると、その DataList 項目が編集モードでレンダリングされる各製品に [編集] ボタンを追加する必要があります。 まず、デザイナーまたは宣言によって ItemTemplate に [編集] ボタンを追加します。 [編集] ボタンの CommandName プロパティを [Edit] に設定してください。

この [編集] ボタンを追加したら、少し時間を取ってブラウザーでページを表示します。 この追加により、各製品登録情報に [編集] ボタンが含まれているはずです。

[編集] ボタンが追加された DataList EditItemTemplate を示すスクリーンショット。

図 12: EditItemTemplate に [更新] ボタンと [キャンセル] ボタンを追加する (クリックしてフルサイズの画像を表示)

ボタンをクリックするとポストバックが発生しますが、製品登録情報は編集モードに "なりません"。 製品を編集可能にするには、次の作業を行う必要があります。

  1. DataList の EditItemIndex プロパティを、[編集] ボタンをクリックされた DataListItem のインデックスに設定します。
  2. データを DataList に再バインドします。 DataList が再レンダリングされると、DataList の EditItemIndex に対応する ItemIndex を持つ DataListItem で、その EditItemTemplate を使用してレンダリングされます。

[編集] ボタンをクリックすると DataList の EditCommand イベントが発生するため、次のコードを使用して EditCommand イベント ハンドラーを作成します。

protected void DataList1_EditCommand(object source, DataListCommandEventArgs e)
{
    // Set the DataList's EditItemIndex property to the
    // index of the DataListItem that was clicked
    DataList1.EditItemIndex = e.Item.ItemIndex;
    // Rebind the data to the DataList
    DataList1.DataBind();
}

EditCommand イベント ハンドラーは、2 番目の入力パラメーターとして型 DataListCommandEventArgs のオブジェクトで渡されます。これには、編集ボタンがクリックされた DataListItem への参照が含まれます (e.Item)。 イベント ハンドラーでは、最初に DataList の EditItemIndex を編集可能な DataListItem オブジェクトの ItemIndex に設定してから、DataList の DataBind() メソッドを呼び出して DataList にデータを再バインドします。

このイベント ハンドラーを追加した後、ブラウザーでページを見直します。 [編集] ボタンをクリックすると、クリックした製品が編集可能になります (図 13 を参照)。

[編集] ボタンをクリックすると、製品が編集可能になります

図 13: [編集] ボタンをクリックすると、製品が編集可能になります (クリックしてフルサイズの画像を表示)

手順 6: ユーザーの変更を保存する

編集した製品の [更新] または [キャンセル] ボタンをクリックしても、この時点では何も行われません。この機能を追加するには、DataList の UpdateCommandCancelCommand イベントのイベント ハンドラーを作成する必要があります。 まず、CancelCommand イベント ハンドラーを作成します。このハンドラーは、編集された製品の [キャンセル] ボタンがクリックされ、DataList を編集前の状態に戻すタスクが指示されたときに実行されます。

DataList がそのすべての項目を読み取り専用モードでレンダリングするには、次の操作を行う必要があります。

  1. DataList の EditItemIndex プロパティを、存在しない DataListItem インデックスのインデックスに設定します。 -1 は安全な選択肢です。DataListItem インデックスは 0 から始まるためです。
  2. データを DataList に再バインドします。 DataList のEditItemIndexに対応するDataListItem ItemIndexがないため、DataList 全体が読み取り専用モードでレンダリングされます。

これらの手順は、次のイベント ハンドラー コードを使用して実行できます。

protected void DataList1_CancelCommand(object source, DataListCommandEventArgs e)
{
    // Set the DataList's EditItemIndex property to -1
    DataList1.EditItemIndex = -1;
    // Rebind the data to the DataList
    DataList1.DataBind();
}

さらに、[キャンセル] ボタンをクリックすると、DataList が編集前の状態に戻ります。

最後に完了する必要があるイベント ハンドラーは、UpdateCommand イベント ハンドラーです。 このイベント ハンドラーでは、次の操作を行う必要があります。

  1. プログラムを使用して、ユーザーが入力した製品名と価格、および編集された製品の ProductID にアクセスします。
  2. ProductsBLL クラスで適切な UpdateProduct オーバーロードを呼び出して、更新プロセスを開始します。
  3. DataList の EditItemIndex プロパティを、存在しない DataListItem インデックスのインデックスに設定します。 -1 は安全な選択肢です。DataListItem インデックスは 0 から始まるためです。
  4. データを DataList に再バインドします。 DataList のEditItemIndexに対応するDataListItem ItemIndexがないため、DataList 全体が読み取り専用モードでレンダリングされます。

手順 1 と 2 は、ユーザーの変更を保存する責任を担います。手順 3 と 4 では、変更が保存された後に DataList を編集前の状態に戻します。CancelCommand イベント ハンドラーで実行される手順と同じです。

更新された製品名と価格を取得するには、FindControl メソッドを使用してプログラムで EditItemTemplate の TextBox Web コントロールを参照する必要があります。 また、編集した製品の ProductID 値を取得する必要があります。 最初に ObjectDataSource を DataList にバインドしたとき、Visual Studio では DataList の DataKeyField プロパティをデータ ソース (ProductID) の主キー値に割り当てしました。 この値は、DataList の DataKeys コレクションから取得できます。 少し時間を使って、DataKeyField プロパティが実際に ProductID に設定されていることを確認します。

次のコードは、4 つの手順を実装します。

protected void DataList1_UpdateCommand(object source, DataListCommandEventArgs e)
{
    // Read in the ProductID from the DataKeys collection
    int productID = Convert.ToInt32(DataList1.DataKeys[e.Item.ItemIndex]);
    // Read in the product name and price values
    TextBox productName = (TextBox)e.Item.FindControl("ProductName");
    TextBox unitPrice = (TextBox)e.Item.FindControl("UnitPrice");
    string productNameValue = null;
    if (productName.Text.Trim().Length > 0)
        productNameValue = productName.Text.Trim();
    decimal? unitPriceValue = null;
    if (unitPrice.Text.Trim().Length > 0)
        unitPriceValue = Decimal.Parse(unitPrice.Text.Trim(),
            System.Globalization.NumberStyles.Currency);
    // Call the ProductsBLL's UpdateProduct method...
    ProductsBLL productsAPI = new ProductsBLL();
    productsAPI.UpdateProduct(productNameValue, unitPriceValue, productID);
    // Revert the DataList back to its pre-editing state
    DataList1.EditItemIndex = -1;
    DataList1.DataBind();
}

イベント ハンドラーは、DataKeys コレクションから編集された製品の ProductID を読み取ることで開始します。 次に、EditItemTemplate の 2 つの TextBox が参照され、その Text プロパティがローカル変数 productNameValueunitPriceValue に格納されます。 Decimal.Parse() メソッドを使用して UnitPrice TextBox から値を読み取り、入力された値に通貨記号が含まれている場合でも Decimal 値に正しく変換できるようにします。

Note

TextBox の Text プロパティに値が指定されている場合、ProductNameUnitPrice TextBox の値は productNameValue 変数と unitPriceValue 変数にのみ割り当てられます。 それ以外の場合は、値 Nothing が変数に使用され、データベース NULL 値を使用してデータを更新する効果があります。 つまり、このコードでは、空の文字列をデータベース NULL 値に変換します。これは、GridView、DetailsView、FormView コントロールの編集インターフェイスの既定の動作です。

値を読み取った後、ProductsBLL クラス の UpdateProduct メソッドが呼び出され、製品の名前、価格、ProductID が渡されます。 イベント ハンドラーは、CancelCommand イベント ハンドラーとまったく同じロジックを使用して、DataList を編集前の状態に戻すことによって完了します。

EditCommandCancelCommandUpdateCommand イベント ハンドラーが完了すると、訪問者は製品の名前と価格を編集できます。 図 14 から 16 は、この編集ワークフローの動作を示しています。

最初にページにアクセスすると、すべての製品が読み取り専用モードになります

図 14: 最初にページにアクセスすると、すべての製品が読み取り専用モードになります (クリックしてフルサイズの画像を表示)

製品名または価格を更新するには、[編集] ボタンをクリックします。

図 15: 製品名または価格を更新するには、[編集] ボタンをクリックします (クリックしてフルサイズの画像を表示)

値を変更した後、[更新] をクリックして読み取り専用モードに戻ります

図 16: 値を変更した後、[更新] をクリックして読み取り専用モードに戻ります (クリックしてフルサイズの画像を表示)

手順 7: 削除機能の追加

DataList に削除機能を追加する手順は、編集機能を追加する手順と似ています。 要するに、クリックしたときに ItemTemplate に削除ボタンを追加する必要があります。

  1. DataKeys コレクションを介して、対応する製品の ProductID を読み取ります。
  2. ProductsBLL クラス の DeleteProduct メソッドを呼び出して削除を実行します。
  3. データを DataList に再バインドします。

まず、[削除] ボタンを ItemTemplate に追加します。

クリックすると、CommandName が Edit、Update、または Cancel のボタンは、追加のイベントと共に DataList の ItemCommand イベントを発生させます (たとえば、Edit を使用すると EditCommand イベントも発生します)。 同様に、CommandName プロパティが Delete に設定されている DataList 内の Button、LinkButton、または ImageButton では、DeleteCommand イベントが発生します (ItemCommand と共に)。

ItemTemplate の [編集] ボタンの横に [削除] ボタンを追加し、その CommandName プロパティを Delete に設定します。 この Button コントロールを追加すると、DataList の ItemTemplate 宣言構文は次のようになります。

<ItemTemplate>
    <h5>
        <asp:Label runat="server" ID="ProductNameLabel"
            Text='<%# Eval("ProductName") %>' />
    </h5>
    Price: <asp:Label runat="server" ID="Label1"
                Text='<%# Eval("UnitPrice", "{0:C}") %>' />
    <br />
    <asp:Button runat="server" id="EditProduct" CommandName="Edit"
        Text="Edit" />
     
    <asp:Button runat="server" id="DeleteProduct" CommandName="Delete"
        Text="Delete" />
    <br />
    <br />
</ItemTemplate>

次に、次のコードを使用して、DataList の DeleteCommand イベントのイベント ハンドラーを作成します。

protected void DataList1_DeleteCommand(object source, DataListCommandEventArgs e)
{
    // Read in the ProductID from the DataKeys collection
    int productID = Convert.ToInt32(DataList1.DataKeys[e.Item.ItemIndex]);
    // Delete the data
    ProductsBLL productsAPI = new ProductsBLL();
    productsAPI.DeleteProduct(productID);
    // Rebind the data to the DataList
    DataList1.DataBind();
}

[削除] ボタンをクリックするとポストバックが発生し、DataList の DeleteCommand イベントが発生します。 イベント ハンドラーでは、クリックされた製品の ProductID 値が DataKeys コレクションからアクセスされます。 次に、ProductsBLL クラスの DeleteProduct メソッドを呼び出して製品を削除します。

製品を削除した後、DataList (DataList1.DataBind()) にデータを再バインドすることが重要です。そうしないと、DataList は削除された製品を引き続き表示します。

まとめ

DataList には、GridView で利用できるポイント アンド クリックの編集と削除のサポートがありませんが、短いコードでこれらの機能を含むように拡張できます。 このチュートリアルでは、削除可能で名前と価格を編集できる製品の 2 列の一覧を作成する方法について説明しました。 編集と削除のサポートの追加とは、適切な Web コントロール ItemTemplateEditItemTemplate を含め、対応するイベント ハンドラーを作成し、ユーザーが入力した値と主キーの値を読み取り、ビジネス ロジック レイヤーとやり取りすることです。

DataList には基本的な編集機能と削除機能が追加されていますが、より高度な機能はありません。 たとえば、入力フィールドの検証はありません。ユーザーが "Too expensive" という価格を入力した場合、"Too expensive" を Decimal に変換しようとすると、Decimal.Parse から例外がスローされます。 同様に、ビジネス ロジックまたはデータ アクセス レイヤーでデータの更新に問題がある場合、ユーザーには標準エラー画面が表示されます。 [削除] ボタンに何らかの確認がなければ、誤って製品を削除する可能性が高すぎます。

今後のチュートリアルでは、編集のユーザー エクスペリエンスを向上させる方法について説明します。

プログラミングに満足!

著者について

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

特別な感謝

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