SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

現役エンジニア直伝! 「現場」で使えるコンポーネント活用術(MultiRow)

複雑な一覧だからこそGUI画面でデザインしたい! Webで1レコード複数行表示を実現するMultiRow for ASP.NETの実力

1レコード複数行表示を実現するMultiRow for ASP.NETの実力(前編)

  • このエントリーをはてなブックマークに追加

ダウンロード サンプルソース (81.3 KB)

 ASP.NETでDB上の1レコードを複数行として表示させるためには、通常、なかなか骨の折れる作業が必要になります。しかし、MultiRow for ASP.NETを利用することで容易に実現可能です。今回は、Repeaterコントロールを使った場合の実装方法と比較しながら、MultiRow for ASP.NETの魅力に迫ってみたいと思います。

  • このエントリーをはてなブックマークに追加

1レコード複数行表示をWebで容易に実現するMultiRow for ASP.NET

 ASP.NETでDB上の1レコードを複数行として表示させるためには、GridViewコントロールでの実装は難しく、Repeaterコントロールを使ってHTMLの<table>タグを駆使して実装しなければなりません。

 <table>タグを駆使する方法は、ASP.NET以外の方法でWebアプリを作成するときも同じようなものですが、例えば交互に背景色を切り替えて表を見やすくするときには同じ行定義を<ItemTemplate>タグと<AlternatingItemTemplate>タグに定義しなければならないなど、使い勝手の悪さが気になります。ソート機能やページ制御についても工夫をしなければなりません。

 また、ASP.NETのWebフォーム用コントロールの使いやすさに慣れてしまうと、Repeaterコントロールは必ずしも使いやすいコントロールとは言えません。Windowsフォーム用にグレープシティから発売されている、MultiRowコントロールのASP.NET版でもあればと数年前から待ちわびていましたが、遂にMultiRow for ASP.NETが登場してくれました。

Repeaterコントロールを使った実装例

 MultiRow for ASP.NETでどれくらい楽ができるかを知るために、まずはRepeaterコントロールを使った場合、どれくらい苦労するかを再検証してみましょう。サンプルソースにこちらのRepeaterコントロールを使った場合の完成版も同梱してあるので、参考にしてみてください(サンプルソース内「CZ1007RepeterControlSample」)。

 作成する複数行表示は、図1のようになります。面倒なのでページ制御やソート機能は実装していません。

図1 Repeaterコントロールによる実現例
図1 Repeaterコントロールによる実現例

 このデザインを実現するためのHTMLは、リスト1のようになります。

リスト1 Repeaterコントロールの使用例(RepeaterControlSample.aspxファイル)
<form id="RepeaterControlSample_Form" runat="server">
<div>
    <asp:Repeater ID="Repeater1" runat="server">
    <HeaderTemplate>
    <table border='1'>
    <tr><th rowspan="2">日付</th><th colspan="5">製品名</th></tr>
    <tr><th>伝票No</th><th>区分</th><th>単価</th><th>数量</th><th>金額z</th></tr>
    </HeaderTemplate>
    <ItemTemplate>
    <tr style="background-color:White;">
    <td rowspan="2"><%# Format(DataBinder.Eval(Container.DataItem, "Date"), "yyyy/MM/dd")%> </td>
    <td colspan="5"><%# DataBinder.Eval(Container.DataItem, "Products").ToString%> </td>
    </tr>
    <tr style="background-color:White;">
    <td><%# DataBinder.Eval(Container.DataItem, "SlipNo")%> </td>
    <td><%# DataBinder.Eval(Container.DataItem, "Category")%> </td>
    <td style="text-align:right;"><%# Format(DataBinder.Eval(Container.DataItem, "UnitPrice"), "#,##0")%> </td>
    <td style="text-align:right;"><%# Format(DataBinder.Eval(Container.DataItem, "Number"), "#,##0")%> </td>
    <td style="text-align:right;"><%# Format(DataBinder.Eval(Container.DataItem, "UnitPrice") *
                                             DataBinder.Eval(Container.DataItem, "Number"), "#,##0")%> </td>
    </tr>
    </ItemTemplate>
    <AlternatingItemTemplate>
    <tr style="background-color:#e0ffe0;">
    <td rowspan="2"><%# Format(DataBinder.Eval(Container.DataItem, "Date"), "yyyy/MM/dd")%> </td>
    <td colspan="5"><%# DataBinder.Eval(Container.DataItem, "Products").ToString%> </td>
    </tr>
    <tr style="background-color:#e0ffe0;">
    <td><%# DataBinder.Eval(Container.DataItem, "SlipNo")%> </td>
    <td><%# DataBinder.Eval(Container.DataItem, "Category")%> </td>
    <td style="text-align:right;"><%# Format(DataBinder.Eval(Container.DataItem, "UnitPrice"), "#,##0")%> </td>
    <td style="text-align:right;"><%# Format(DataBinder.Eval(Container.DataItem, "Number"), "#,##0")%> </td>
    <td style="text-align:right;"><%# Format(DataBinder.Eval(Container.DataItem, "UnitPrice") *
                                             DataBinder.Eval(Container.DataItem, "Number"), "#,##0")%> </td>
    </tr>
    </AlternatingItemTemplate>
    <FooterTemplate>
    </table>
    </FooterTemplate>
    </asp:Repeater>
</div>
</form>

 Repeaterコントロールのデータソースとして指定したDataSetに格納されたレコードを<td>タグで囲んで出力するために、DataBinder.Evalを使っています。デザイナの[デザイン]タブでは編集できないため、[コード]タブでHTMLを直書きして行います。

 Repeaterコントロールで交互に背景色を変えるときは、<ItemTemplate>タグと<AlternatingItemTemplate>タグの中に同じ行定義を記述し、<tr>タグのStyleに指定するBackground-Colorを別の背景色にすることで実現します。

 この実現方法の場合、データの配置などを変えるときは、次のような作業を行わなくてはなりません。

  1. <HeaderTemplate>でヘッダ行の変更
  2. <ItemTemplate>でデータ行の変更
  3. (2)の変更を<AlternatingItemTemplate>に反映

 実際、開発現場でお客様からのレビューを受けてデザイン変更していると、つい(3)のステップを忘れてしまうときがあります。私自身、実装していて非常に面倒で嫌になってしまう手順でした。

Repeaterコントロールの実行

 Repeaterコントロールに値を表示するためには、リスト2のようにDataSetのテーブルをDataSourceプロパティに設定してから、DataBindメソッドを実行します。

リスト2 Repeaterコントロールの使用例(RepeaterControlSample.aspx.vbファイル)
Imports System.Data

Partial Class RepeaterControlSample
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object,
                            ByVal e As System.EventArgs) Handles Me.Load
        If Not Me.IsPostBack Then
            Call GetRecords()
        End If
    End Sub

    Private Function GetRecords() As Boolean
        Dim isOK As Boolean = False
        Using _proc As New CZ1007Bound
            Dim ds As DataSet = _proc.GetRecords("admin", "", "WS-DF502")
            Me.Repeater1.DataSource = ds.Tables("Bill")
            Me.Repeater1.DataBind()
            isOK = True
        End Using
        Return isOK
    End Function
End Class

 次にMultiRow for ASP.NETを使った際の、実現方法を見ていきましょう。

MultiRow for ASP.NETでの効率化例

 それでは、MultiRow for ASP.NETで実現する場合は、どのようになるか確認してみましょう。サンプルソースは、「CZ1007MultiRowSample」です。

そのために、まず事前準備としてツールボックスにMultiRowを追加しなければなりません。

図2 ツールボックスへのMultiRowの追加
図2 ツールボックスへのMultiRowの追加

 ツールボックス上で右クリックし、[アイテムの選択]メニューを選びます。ダイアログボックスが表示されたら、名前空間「GrapeCity.Web.MultiRow」を選択して[OK]をクリックします。名前空間から分かるように、グレープシティ社が開発した製品です。

MultiRowを配置

 MultiRowをWebフォームに配意するためには、ツールボックスからMultiRowのアイコンをWebフォーム上にドラッグ&ドロップします。

図3 MultiRowの初期状態
図3 MultiRowの初期状態

MultiRowをデザイン

 初期状態では図3のようなレイアウトなので、MultiRowのスマートタグからタスクを使って設定を行います。MultiRowタスクでは、レコード追加や削除など基本的な操作性の設定ができます。

図4 MultiRowタスク
図4 MultiRowタスク

 MultiRowの1データ分のデザインは、テンプレートをデザインすることで実現します。テンプレートをグラフィカルにデザインするための機能が「テンプレートデザイナ」です。テンプレートデザイナの起動は、MultiRowタスクから行います。

図5 テンプレートデザイナ
図5 テンプレートデザイナ

 テンプレートデザイナでは、デザイン画面にツールボックスからセルをドラッグ&ドロップしてデザインを決めていきます。特筆すべき点として、セルとセルの間が0のときにスナップ線が表示されることが挙げられます。これは日本の帳票文化では非常に重要で、効率がいい操作性です。

 もちろん、2行に渡るセルや2列にわたるセルも、配置した後でセルの境界線をドラッグすると自由に大きさを変更できます。何種類かセルがあるので、文字列や数値用のセルを目的に応じて選べば、それぞれの属性に合わせた修飾も可能です。

 図5ではヘッダ部分のテキストを中心に表示するようになっています。これは「ColumnHeaderSection1」の部分を選択し、DefaultHeaderCellStyleの、ContentHAlignプロパティとContentVAlignプロパティで設定しています。ヘッダに配置した個々のセルでは設定は行っていません。もし、一部のヘッダのみ違った文字配置にしたいときは、その一部のヘッダセルのところだけを設定することもできます。

 このように、最小限の設置で全体を制御できるのも魅力的です。

図6 デザイン例
図6 デザイン例

 1データごとに交互に背景色を変えたいときは、プロパティウィンドウの「AlterntingRowStyle」で、別の色の設定を追加できます。

図7 データ行ごとの背景色設定例
図7 データ行ごとの背景色設定例

 図7にあるように1行おきだけではなく、RowStyleコレクションに追加していけば、3色以上の色違いにすることもできます。

MultiRowを実行

 MultiRowに値を表示するためには、リスト3のようにDataSetのテーブルを「DataSource」プロパティに設定してから、DataBindメソッドを実行します。

リスト3 MultiRowの使用例(MultiRowSample.aspx.vbファイル)
Imports System.Data

Partial Class MultiRowSample
    Inherits System.Web.UI.Page

    Protected Sub Page_Load(ByVal sender As Object, 
                            ByVal e As System.EventArgs) Handles Me.Load
        If Not Me.IsPostBack Then
            Call GetRecords()
        End If
    End Sub

    Private Function GetRecords() As Boolean
        Dim isOK As Boolean = False
        Using _proc As New CZ1007Bound
            Dim ds As DataSet = _proc.GetRecords("admin", "", "WS-DF502")
            Me.MultiRow1.DataSource = ds.Tables("Bill")
            Me.MultiRow1.DataBind()
            isOK = True
        End Using
        Return isOK
    End Function
End Class
図8 MultiRowの実行例
図8 MultiRowの実行例

MultiRow for ASP.NETでページングを実装する

 MultiRow for ASP.NETにはページングを行うためのプロパティがあります。それがAllowPagingプロパティです。AllowPagingプロパティをTrueに設定しておけばPageSizeプロパティに設定された行数ごとにページングできます。

 このように設定することによりDataSourceに割り当てられたデータソースに含まれているデータ全体からカレントページの先頭位置を算出してPageSizeプロパティの行数だけを表示します。データソース全体を対象にするのでデータソース自身にはページング機能の実装などは不要です。

図9 [ページングを有効にする]にチェックを入れる。デフォルトの設定は1ページ10行表示
図9 [ページングを有効にする]にチェックを入れる、デフォルトの設定は1ページ10行表示

MultiRow for ASP.NETでObjectDataSourceのページングを利用する

 取り扱うデータが膨大でパフォーマンスが気になる場合は、少し手間がかかりますが、ObjectDataSourceのページング機能を併用することで、高パフォーマンスなページの作成が可能です(サンプルソース「CZ1007PagerSample」)。

図10 ページング機能付きMultiRow定義例
図10 ページング機能付きMultiRow定義例

 今回、データベースからの値の入出力は、すべて「CZ1007Bound」クラスで実装しています。そこで、ObjectDataSourceを介してページングに必要な動作を行うメソッドを「CZ1007Bound」クラスに追加し、ページング機能付きMultiRowを実現してみましょう。

ページング機能付きデータアクセスクラス

 「CZ1007Bound」クラスにページング機能を実装するためには、いくつかの約束事を守ったメソッドを実装しなければなりません。

 必要なメソッドは「レコード数を取得する」メソッドと、「先頭から数えてn個目からm個のレコードを取得する」メソッドの2つです。この2つのメソッドのパラメタは、同一にしなければなりません。

 今回のサンプルでは、「レコード数を取得する」メソッドとしてGetNumberOfOrdersメソッドを実装します。本来は先頭3つのパラメタだけで十分ですが、ObjectDataSourceで使われることを前提として、startRowIndexmaximumRowsパラメタが追加されています。

リスト4 GetNumberOfOrders
Public Function GetNumberOfOrders(ByVal userID As String,
                                  ByVal password As String,
                                  ByVal billNo As String,
                                  ByVal startRowIndex As Integer,
                                  ByVal maximumRows As Integer) As Integer
    Dim rows As Integer = 0

    Using _cn As New OleDb.OleDbConnection()
        _cn.ConnectionString = String.Format(System.Configuration.ConfigurationManager.AppSettings("ConnectionString"),
                                             userID,
                                             password)
        _cn.Open()
        Using _cmd As New OleDb.OleDbCommand
            _cmd.Connection = _cn
            _cmd.CommandText =
                "SELECT COUNT(*) " &
                  "FROM Customers " &
                 "INNER JOIN (Bill INNER JOIN BillCondition " &
                                     "ON Bill.BillNo = BillCondition.BillNo)" &
                    "ON Customers.CustomerID = Bill.CustomerID " &
                 "WHERE Bill.BillNo=? "
            _cmd.Parameters.AddWithValue("@billNo", billNo)
            rows = CType(_cmd.ExecuteScalar, Integer)
        End Using
        _cn.Close()
    End Using
    Return rows
End Function

 「先頭から数えてn個目からm個のレコードを取得する」メソッドとしては、GetRecordsByIndexメソッドを実装します。nmは、それぞれstartRowIndexmaximumRowsというパラメタ値として、このメソッドに渡ってきます。

リスト5 CZ1007Bound.vbファイルの内容
Public Function GetRecordsByIndex(ByVal userID As String,
                                  ByVal password As String,
                                  ByVal billNo As String,
                                  ByVal startRowIndex As Integer,
                                  ByVal maximumRows As Integer) As DataSet
    Dim ds As New DataSet
    Using _cn As New OleDb.OleDbConnection()
     :
   (中略)
     :
    End Using
    Return ds
End Function

ページング機能付きデータアクセスクラスをObjectDataSourceで利用

 「CZ1007Bound」クラスをObjectDataSourceで利用するために、設定が必要なメソッドとしては次のものがあります。

表1 プロパティ設定値
プロパティ 用途 設定値
TypeName クラス名を指定 CZ1007Bound
SelectMethod レコード取得用メソッド名 GetRecordsByIndex
SelectCountMethod 件数取得用メソッド名 GetNumberOfOrders
EnablePaging True:ページング True

 ObjectDataSourceに対してページング機能を有効(EnablePaging=True)にすると、StartRowIndexParameterNameメソッドとMaximumRowsParameterNameメソッドの設定値も有効になります。

 StartRowIndexParameterNameメソッドは、カレントページの先頭に表示する行位置を「CZ1007Bound」クラスに渡すためのパラメタ名で、デフォルト値として「startRowIndex」が指定されています。

 MaximumRowsParameterNameメソッドは、ページ内の行数を「CZ1007Bound」クラスに渡すためのパラメタ名で、デフォルト値として「maximumRows」が指定されています。

 ここで指定したパラメタ名をSelect時に使うためのは、パラメータコレクションエディターを使います。

図11 パラメータコレクションエディター
図11 パラメータコレクションエディター

 このように設定しておけば、リスト3に相当するコードを記述しなくても、「CZ1007Bound」クラスのメソッドが自動的に呼び出されてデータを取得します。そのため「aspx.vb」ファイルの内容は、リスト6のように初期状態のままになっています。

リスト6 MultiRowSample.aspx.vbファイルの内容
Partial Class MultiRowSample
    Inherits System.Web.UI.Page

End Class

実行

図12 ページング機能付きMultiRowの実行例
図12 ページング機能付きMultiRowの実行例

 フッタのページ数をクリックすれば、該当ページに移動もできます。クリックするたびにパラメタにも適切な値が設定されて、「CZ1007Bound」クラスのGetRecordsByIndexメソッドが自動的に呼び出されます。

次回予告

 今回は参照画面について、Repeaterコントロールよりも簡単な使い方を紹介しました。次回は、MultiRowを使った更新画面など、さらに詳細な使い方を応用編として紹介します。

製品情報

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/5351 2010/09/13 16:59

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング