●得意先別受注情報を階層化して表示 (ch66NestedControl1.aspx)

 

DataList1DataList2をネストさせて得意先別の受注情報を表示します。さらに、DataList2DataGrid1をネストさせて受注明細を表示します。DataList1Customers表(得意先)を表示するには、パッケージ(CustomerPackage)に登録されているストアドプロシージャ(GetCustomers)を使用します。このストアドプロシージャは、Customers表からすべての行(レコード)を抽出します。

 

DataList2に得意先の受注情報を表示するには、パッケージ(OrderPackage)に登録されているストアドプロシージャ(GetOrdersByCustomerID)を使用します。このストアドプロシージャは、パラメータに指定した得意先のすべての受注情報を抽出します。

 

DataGrid1に受注明細を表示するには、パッケージ(OrderDetailPackage)に登録されているストアドプロシージャ(GetOrderDetailsByOrderID)を使用します。このストアドプロシージャは、パラメータに指定した受注IDの受注明細を抽出します。

 

iSQL*PlusまたはSQL*Plusを起動して、事前にパッケージ仕様部とパッケージ本体部を作成してください。

 

パッケージ仕様部

CustomerPackage.sql

CREATE OR REPLACE PACKAGE CustomerPackage AS

  TYPE rcurCustomers IS REF CURSOR;

  PROCEDURE GetCustomers(

    orcurCustomers OUT rcurCustomers);

END CustomerPackage;

 

OrderPackage.sql

CREATE OR REPLACE PACKAGE OrderPackage AS

  TYPE rcurOrders IS REF CURSOR;

  PROCEDURE GetOrdersByCustomerID(

    orcurOrders OUT rcurOrders,

    iCustomerID IN NUMBER);

END OrderPackage;

 

OrderDetailPackage.sql

CREATE OR REPLACE PACKAGE OrderDetailPackage AS

  TYPE rcurOrderDetails IS REF CURSOR;

  PROCEDURE GetOrderDetailsByOrderID(

    orcurOrderDetails OUT rcurOrderDetails,

    iOrderID IN NUMBER);

END OrderDetailPackage;

 

 

パッケージ本体部

CustomerPackageBody.sql

CREATE OR REPLACE PACKAGE BODY CustomerPackage AS

  PROCEDURE GetCustomers(

    orcurCustomers OUT rcurCustomers) IS

  BEGIN

    OPEN orcurCustomers FOR

      SELECT *

      FROM Customers

      ORDER BY CustomerID;

  END GetCustomers;

END CustomerPackage;

 

OrderPackageBody.sql

CREATE OR REPLACE PACKAGE BODY OrderPackage AS

  PROCEDURE GetOrdersByCustomerID(

    orcurOrders OUT rcurOrders,

    iCustomerID IN NUMBER) IS

  BEGIN

    OPEN orcurOrders FOR

      SELECT *

      FROM Orders

      WHERE CustomerID = iCustomerID

      ORDER BY OrderID;

  END GetOrdersByCustomerID;

END OrderPackage;

 

OrderDetailPackageBody.sql

CREATE OR REPLACE PACKAGE BODY OrderDetailPackage AS

  PROCEDURE GetOrderDetailsByOrderID(

    orcurOrderDetails OUT rcurOrderDetails,

    iOrderID IN NUMBER) IS

  BEGIN

    OPEN orcurOrderDetails FOR

      SELECT OrderDetails.*, Products.ProductName

      FROM Products

      INNER JOIN OrderDetails

      ON Products.ProductID = OrderDetails.ProductID

      WHERE OrderDetails.OrderID = iOrderID

      ORDER BY OrderDetails.ProductID;

  END GetOrderDetailsByOrderID;

END OrderDetailPackage;

 

このサンプルでは、以下のノウハウを習得することができます。

 

DataListDataListをネストさせる方法

DataListDataGridをネストさせる方法

DataListItemTemplateを追加する方法

DataListSelectedIndexCangedイベントの使い方

 

1. 新規フォルダ作成

 

ソリューションエクスプローラから[ch6]を右クリックして、新規フォルダ[img]を作成します。本書サンプルのフォルダ(ch6\img)からすべてイメージファイルをコピー&ペーストします。

 

fig6-6-1

新規フォルダ(img)にイメージファイルをコピー&ペーストする

 

2. Webフォーム追加

 

ソリューションエクスプローラからフォルダ[ch6]を右クリックして、新規Webフォーム「ch66NestedControl1.aspx」を追加します。

 

3. DataList1作成

 

ツールボックスの[Webフォーム]からDataListをドラッグ&ドロップします。デザイナにDataList1のオブジェクトが作成されます。

 

fig6-6-2

デザイナにDataList1作成

 

4. DataList1ItemTemplate追加

 

デザイナの最下位に表示されている[HTML]タブをクリックして、HTMLビューに切り替えます。<asp:DataList>...</asp:DataList>の間に、次の<ItemTemplate>...</ItemTemplate>を追加します。ここで追加するItemTemplateは、後述する「DataList1のテンプレート作成」にて作成したものをコピー&ペーストします。

 

<asp:DataList id="DataList1" runat="server">

  <ItemTemplate>

    <TABLE id="Table1" border="0">

      <TR>

        <TD>

          <asp:ImageButton id="ImageButton1" runat="server"

            commandname="Select" ImageUrl="img/bookclose2.gif">

          </asp:ImageButton>

        </TD>

        <TD>

          <asp:Label id=lblCompanyName runat="server"

            Text='<%# Container.DataItem("CompanyName") %>'>

          </asp:Label>

        </TD>

      </TR>

      <TR>

        <TD></TD>

        <TD>

          <asp:DataList id="DataList2" Runat="server"

            OnSelectedIndexChanged="DataList2_SelectedIndexChanged"

            Visible="False">

          </asp:DataList>

        </TD>

      </TR>

    </TABLE>

  </ItemTemplate>

</asp:DataList>

 

5. DataList2にテンプレート追加

 

DataList2<asp:DataList>...</asp:DataList>の間に、次のHeaderTemplateItemTemplateFooterTemplateを追加します。ここで追加するテンプレートは、後述する「DataList2のテンプレート作成」にて作成したものをコピー&ペーストします。

 

<asp:DataList id="DataList2" Runat="server"

  OnSelectedIndexChanged="DataList2_SelectedIndexChanged"

  Visible="False">

  <HeaderTemplate>

    <table id="Table2" border="0">

      <tr>

        <th></th>

        <th>受注ID</th>

        <th>受注日</th>

        <th>出荷日</th>

      </tr>

  </HeaderTemplate>

  <ItemTemplate>

    <tr>

      <td>

        <asp:ImageButton ID="ImageButton2" Runat="server"

          CommandName="Select" ImageUrl="img/bookclose.gif">

        </asp:ImageButton>

      </td>

      <td>

        <asp:Label ID=lblOrderID Runat=server

          text='<%# Container.DataItem("OrderID") %>'>

        </asp:Label>

      </td>

      <td>

        <asp:Label ID="lblOrderDate" Runat=server

          text='<%# DataBinder.Eval(Container.DataItem, "OrderDate", "{0:d}") %>'>

        </asp:Label>

      </td>

      <td>

        <asp:Label ID="lblShippedDate" Runat=server

          text='<%# DataBinder.Eval(Container.DataItem, "ShippedDate","{0:d}") %>'>

        </asp:Label>

      </td>

    </tr>

    <tr>

      <td></td>

      <td colspan="3">

        <asp:DataGrid ID="DataGrid1" Runat="server"

          AutoGenerateColumns="False" Visible="False" BorderColor="#CCCCCC"

          BorderStyle="None" BorderWidth="1px" BackColor="White"

          CellPadding="4" GridLines="Horizontal"

          ForeColor="Black" Width="220px">

          <SelectedItemStyle Font-Bold="True" ForeColor="White"

            BackColor="#CC3333">

          </SelectedItemStyle>

          <HeaderStyle Font-Bold="True" HorizontalAlign="Center"

            ForeColor="White" BackColor="#333333">

          </HeaderStyle>

          <FooterStyle ForeColor="Black" BackColor="#CCCC99">

          </FooterStyle>

          <Columns>

            <asp:BoundColumn DataField="ProductName"

              HeaderText="受注商品">

            </asp:BoundColumn>

            <asp:BoundColumn DataField="Quantity"

              HeaderText="数量" DataFormatString="{0:n0}">

              <HeaderStyle HorizontalAlign="Right"></HeaderStyle>

              <ItemStyle HorizontalAlign="Right"></ItemStyle>

            </asp:BoundColumn>

          </Columns>

          <PagerStyle HorizontalAlign="Right"

            ForeColor="Black" BackColor="White">

          </PagerStyle>

        </asp:DataGrid>

      </td>

    </tr>

  </ItemTemplate>

  <FooterTemplate>

    </table>

  </FooterTemplate>

</asp:DataList>

 

6. デザインビューで確認

 

HTMLビューの最下位から[デザイン]タブをクリックして、デザインビューに切り替えます。

 

fig6-6-3

デザインビューで確認

 

7. コードビューに切り替え

 

メニューバーから[表示][コード]を選択してコードビューに切り替えます。クラスモジュールの先頭に、以下のImportsステートメントを追加します。

 

Imports System.Data

Imports Oracle.DataAccess.Client

Imports Oracle.DataAccess.Types

 

Webフォームデザイナで生成されたコード」の左側の+をクリックして展開します。Protected WithEvents DataList1...の直後に、以下のコードを追加します。

 

Protected WithEvents DataList1 As System.Web.UI.WebControls.DataList

Protected WithEvents DataList2 As System.Web.UI.WebControls.DataList

 

 

fig6-6-4

Protected WithEvents DataList2...を追加

 

Page_Loadイベントに、以下のコードを追加します。

 

Private Sub Page_Load(ByVal sender As System.Object,

cccByVal e As System.EventArgs) Handles MyBase.Load

  If Not IsPostBack Then

    BindCustomersList()

  End If

End Sub

 

クラスモジュールの最後に、Sub BindCustomerListFunction CreateCustomersDataViewFunction CreateOrdersDataViewFunction CreateOrderDetailsDataViewを追加します。

 

Private Sub BindCustomersList()

  With DataList1

    .DataSource = CreateCustomersDataView()

    .DataKeyField = "CustomerID"

    .DataBind()

  End With

End Sub

 

Private Function CreateCustomersDataView() As DataView

  Dim con As New OracleConnection(ConfigurationSettings.AppSettings("conStringOraNw"))

  Dim da As New OracleDataAdapter

  Dim cmd As New OracleCommand("CustomerPackage.GetCustomers", con)

  Dim ds As New DataSet

 

  With cmd

    .CommandType = CommandType.StoredProcedure

    .Parameters.Add("1", OracleDbType.RefCursor, ParameterDirection.Output)

  End With

  da.SelectCommand = cmd

  da.Fill(ds)

  Return ds.Tables(0).DefaultView

End Function

 

Private Function CreateOrdersDataView(ByVal intCustomerID As Integer) As DataView

  Dim con As New OracleConnection(ConfigurationSettings.AppSettings("conStringOraNw"))

  Dim da As New OracleDataAdapter

  Dim cmd As New OracleCommand("OrderPackage.GetOrdersByCustomerID", con)

  Dim ds As New DataSet

 

  With cmd

    .CommandType = CommandType.StoredProcedure

    .BindByName = True

    .Parameters.Add("orcurOrders", OracleDbType.RefCursor, ParameterDirection.Output)

    .Parameters.Add("iCustomerID", OracleDbType.Int32).Value = intCustomerID

  End With

  da.SelectCommand = cmd

  da.Fill(ds)

  Return ds.Tables(0).DefaultView

End Function

 

Private Function CreateOrderDetailsDataView(ByVal intOrderID As Integer) As DataView

  Dim con As New OracleConnection(ConfigurationSettings.AppSettings("conStringOraNw"))

  Dim da As New OracleDataAdapter

  Dim cmd As New OracleCommand("OrderDetailPackage.GetOrderDetailsByOrderID", con)

  Dim ds As New DataSet

 

  With cmd

    .CommandType = CommandType.StoredProcedure

    .BindByName = True

    .Parameters.Add("orcurOrderDetails", OracleDbType.RefCursor, ParameterDirection.Output)

    .Parameters.Add("iOrderID", OracleDbType.Int32).Value = intOrderID

  End With

  da.SelectCommand = cmd

  da.Fill(ds)

  Return ds.Tables(0).DefaultView

End Function

 

コードビュー左上の「クラス名」のドロップダウンリストから[DataList1]、右上の「メソッド名」のドロップダウンリストから[SelectedIndexChanged]を選択します。DataList1_SelectedIndexChangedイベントが生成されたら、以下のコードを追加します。

 

Private Sub DataList1_SelectedIndexChanged(ByVal sender As Object,

cccByVal e As System.EventArgs)

cccHandles DataList1.SelectedIndexChanged

  Dim ibtn As ImageButton = CType(DataList1.SelectedItem.FindControl("ImageButton1"), ImageButton)

  Dim dl As DataList = CType(DataList1.SelectedItem.FindControl("DataList2"), DataList)

  Dim intCustomerID As Integer = DataList1.DataKeys(DataList1.SelectedIndex)

 

  If dl.Visible Then

    dl.Visible = False

    ibtn.ImageUrl = "img/bookclose2.gif"

  Else

    dl.Visible = True

    dl.DataSource = CreateOrdersDataView(intCustomerID)

    dl.DataKeyField = "OrderID"

    dl.DataBind()

    ibtn.ImageUrl = "img/bookopen2.gif"

  End If

End Sub

 

 

コードビュー左上の「クラス名」のドロップダウンリストから[DataList2]、右上の「メソッド名」のドロップダウンリストから[SelectedIndexChanged]を選択します。DataList2_SelectedIndexChangedイベントが生成されたら、以下のコードを追加します。それから、Private Sub DataList2Public Sub DataList2に書き換えます。

 

Public Sub DataList2_SelectedIndexChanged(ByVal sender As Object,

cccByVal e As System.EventArgs)

cccHandles DataList2.SelectedIndexChanged

  Dim dl As DataList = CType(sender, DataList)

  Dim ibtn As ImageButton = CType(dl.SelectedItem.FindControl("ImageButton2"), ImageButton)

  Dim dg As DataGrid = CType(dl.SelectedItem.FindControl("DataGrid1"), DataGrid)

  Dim intOrderID As Integer = dl.DataKeys(dl.SelectedIndex)

 

  If dg.Visible Then

    dg.Visible = False

    ibtn.ImageUrl = "img/bookclose.gif"

  Else

    dg.Visible = True

    dg.DataSource = CreateOrderDetailsDataView(intOrderID)

    dg.DataBind()

    ibtn.ImageUrl = "img/bookopen.gif"

  End If

End Sub

 

8. ブラウザに表示

 

ソリューションエクスプローラから[ch66NestedControl1.aspx]を右クリックしてブラウザに表示します。DataList1Customers表が表示されます。得意先の左側のアイコンをクリックすると、DataList2Orders表が表示されます。受注IDの左側のアイコンをクリックすると、DataGrid1OrderDetails表が表示されます。

 

 

fig6-6-5

図 DataList/DataGridがネストされて表示される

 

  解説

 

このサンプルは、DataList/DataGridが3階層にネストしています。DataList1ItemTemplateには、DataList2がネストします。さらに、DataList2ItemTemplateには、DataGrid1がネストします。

 

DataList1には、OracleデータベースのCustomers表から得意先を表示します。DataList2には、Orders表から得意先の受注情報を表示します。DataGrid1には、OrderDetails表から受注明細を表示します。

 

<asp:DataList id="DataList1" runat="server">

  <ItemTemplate>

    <asp:DataList id="DataList2" Runat="server"

      OnSelectedIndexChanged="DataList2_SelectedIndexChanged"

      Visible="False">

      <HeaderTemplate>...</HeaderTemplate>

      <ItemTemplate>

        <asp:DataGrid ID="DataGrid1" Runat="server"

          AutoGenerateColumns="False" Visible="False">

          <Columns>

            <asp:BoundColumn DataField="ProductName"

              HeaderText="受注商品">

            </asp:BoundColumn>

            <asp:BoundColumn DataField="Quantity"

              HeaderText="数量" DataFormatString="{0:n0}">

            </asp:BoundColumn>

          </Columns>

        </asp:DataGrid>

      </ItemTemplate>

      <FooterTemplate>...</FooterTemplate>

    </asp:DataList>

  </ItemTemplate>

</asp:DataList>

 

DataList1の得意先の左側からアイコンbookclose2をクリックすると、WebページがポストバックされてPage_LoadDataList1_SelectedIndexChangedの順番にイベントが発生します。

 

DataList1_SelectedIndexChangedイベントでは、DataList1オブジェクトのSelectedItemプロパティから、選択したアイテムのDataListItemオブジェクトを取得します。DataListItemオブジェクトのFindControlメソッドを実行して、DataList2のオブジェクトを検索して取得します。

 

DataList2が可視(Visible=True)のときは、VisibleプロパティにFalseを設定します。ImageButtonオブジェクトのImageUrlプロパティに「bookclose2.gifbookclose2URLを設定します。

 

DataList2が不可視(Visible=False)のときは、VisibleプロパティにTrueを設定します。さらに、DataSourceプロパティにOrders表のDataViewオブジェクトを設定して、DataBindメソッドでバインドします。ImageButtonオブジェクトのImageUrlプロパティに「bookopen2.gifbookopen2URLを設定します。

 

Private Sub DataList1_SelectedIndexChanged(ByVal sender As Object,

cccByVal e As System.EventArgs)

cccHandles DataList1.SelectedIndexChanged

  Dim ibtn As ImageButton = CType(DataList1.SelectedItem.FindControl("ImageButton1"), ImageButton)

  Dim dl As DataList = CType(DataList1.SelectedItem.FindControl("DataList2"), DataList)

  Dim intCustomerID As Integer = DataList1.DataKeys(DataList1.SelectedIndex)

 

  If dl.Visible Then

    dl.Visible = False

    ibtn.ImageUrl = "img/bookclose2.gif"

  Else

    dl.Visible = True

    dl.DataSource = CreateOrdersDataView(intCustomerID)

    dl.DataKeyField = "OrderID"

    dl.DataBind()

    ibtn.ImageUrl = "img/bookopen2.gif"

  End If

End Sub

 

DataList2の受注IDの左側からアイコンbookcloseをクリックすると、WebページがポストバックされてPage_LoadDataList2_SelectedIndexChangedの順番にイベントが発生します。

 

DataList2_SelectedIndexChangedイベントでは、DataList2オブジェクトのSelectedItemプロパティから、選択したアイテムのDataListItemオブジェクトを取得します。DataListItemオブジェクトのFindControlメソッドを実行して、DataGrid1のオブジェクトを検索して取得します。

 

DataGrid1が可視(Visible=True)のときは、VisibleプロパティにFalseを設定します。ImageButtonオブジェクトのImageUrlプロパティに「bookclose.gifbookclose URLを設定します。

 

DataGrid1が不可視(Visible=False)のときは、VisibleプロパティにTrueを設定します。さらに、DataSourceプロパティにOrderDetails表のDataViewオブジェクトを設定して、DataBindメソッドでバインドします。ImageButtonオブジェクトのImageUrlプロパティに「bookopen.gifbookopen URLを設定します。

 

Public Sub DataList2_SelectedIndexChanged(ByVal sender As Object,

cccByVal e As System.EventArgs)

cccHandles DataList2.SelectedIndexChanged

  Dim dl As DataList = CType(sender, DataList)

  Dim ibtn As ImageButton = CType(dl.SelectedItem.FindControl("ImageButton2"), ImageButton)

  Dim dg As DataGrid = CType(dl.SelectedItem.FindControl("DataGrid1"), DataGrid)

  Dim intOrderID As Integer = dl.DataKeys(dl.SelectedIndex)

 

  If dg.Visible Then

    dg.Visible = False

    ibtn.ImageUrl = "img/bookclose.gif"

  Else

    dg.Visible = True

    dg.DataSource = CreateOrderDetailsDataView(intOrderID)

    dg.DataBind()

    ibtn.ImageUrl = "img/bookopen.gif"

  End If

End Sub