UTable .NET Framework用 表入力コンポーネント
ドキュメント

フィールドの作成と配置

アーキテクチャの項でも説明しましたが、 フィールドを作成する最も低レベルな方法は、レコードのAddFieldメソッドを呼ぶことです。

    Record.AddField(key, fieldProvider, layout)
    Record.AddField(key, fieldProvider) 'レイアウトを指定しないと、非表示のフィールドになる

この方法を用いると、最も自由にフィールドを作成することができますが、やや煩雑です。 各レコードが同じフィールドを持つという場合、レコードプロバイダを利用してください。

    Dim rp As New CRecordProvider
    rp.AddField(key, fieldProvider, layout)
    rp.AddField(key, fieldProvider)
    Content.SetRecordProvider(rp) 'コンテント内のレコードが定義されたフィールドを持つようになる

レコードプロバイダを用いる方法には、フィールドプロバイダやレイアウトを 各レコードで共有できるという利点もあります。 レコードプロバイダを使用できる場合は、常に使用するようにしてください。

フィールドのレイアウトを指定するには リージョン(UTable.CGrid.CRegion)のオブジェクトを用います。 リージョンオブジェクトを作成する方法は2通りあります。 リージョンクラスのコンストラクタを用いる方法と、レイアウトビルダを用いる方法です。

リージョンクラスのコンストラクタ

リージョンクラスのコンストラクタには以下の2つのオーバーロードがあります。

    New UTable.CGrid.CRegion(row, col, rows, cols) 'フィールドの位置とサイズを指定する
    New UTable.CGrid.CRegion(row, col)             '位置のみを指定する。サイズは1x1となる

rows、colsはそのリージョンがまたがる行および列の数、つまりサイズを表します。 レイアウトを定義する際は、フィールドが一部でも重なり合わないように注意してください。 フィールドが重なりあった場合の動作は未定義です。

リージョンをコンストラクタから生成するのは煩雑です。 問題がなければ、次に説明するレイアウトビルダを用いるようにしてください。

レイアウトビルダ

レイアウトビルダ(CLayoutBuilderクラス)を用いることで、リージョンを簡単に生成できます。 たとえば3つのフィールドが水平に並んだレコードを生成するには以下のように書きます。

    Dim rp As New UTable.CRecordProvider
    With New CLayoutBuilder
        rp.AddField(0, New CTextFieldProvider(), .Next)
        rp.AddField(1, New CTextFieldProvider(), .Next)
        rp.AddField(2, New CTextFieldProvider(), .Next)
    End With

レイアウトビルダはNextメソッドを呼ぶたびに隣のリージョンを生成します。 これにより、ソースコード上での順を入れ替えることで、 フィールドの配置順を入れ替えることができます。

レイアウトビルダには以下のメソッドがあります。

メソッド説明
※コンストラクタ
New()
New(orientation)
引数orientationに、EOrientationの値を指定できます
その値により、NextとSkipメソッドで位置が遷移する方向(オリエンテーション)を制御できます
COL : 列(水平)方向
ROW : 行(垂直)方向
省略すると、オリエンテーションはCOLになります
Next()
Next(rows, cols)
直前の隣のリージョンを生成して返します
最初の呼び出しでは左上端のリージョンを返します
引数rows,colsにリージョンのサイズを指定できます
省略すると1x1のリージョンを返します
Skip()
Skip(step)
位置を移動し、自身への参照を返します
位置を飛ばしたいときに使用してください
引数stepに列(または行)数を指定できます
省略すると1を指定したことになります
Break()
Break(step)
オリエンテーションが
COLならば改行し、列位置が0に戻ります
ROWならば改列し、行位置が0に戻ります
行(または列)をいくつ移動するかを引数stepに指定できます
省略すると1を指定したことになります
自身への参照を返します
Ascend()
Ascend(orientation)
対応するDescendが呼ばれるまでの間、
引数orientationで指定したオリエンテーションが有効になります
省略すると、オリエンテーションはCOLになります
AscendとDescendの呼び出しはネスト可能です
自身への参照を返します
Descend() 対応するAscendを終了します
Descendが行われると、元のオリエンテーションで正常に次のリージョンが生成できるように
行または列位置がAscendが呼ばれた時点の状態にリセットされます
自身への参照を返します
Set(row, col) 行と列の位置を指定した値に設定します
このメソッドを用いる際は、リージョンが重ならないように注意してください
自身への参照を返します

サンプル1

以下のテーブルを生成してみましょう。

次のように書きます。

    With New CLayoutBuilder
        rp.AddField(0, New CFieldProvider("0"), .Next(2, 1)) '高さ2 幅1のフィールド
        rp.AddField(1, New CFieldProvider("1"), .Next(1, 2)) '高さ1 幅2のフィールド
        rp.AddField(2, New CFieldProvider("2"), .Break.Skip.Next) '改行後、重ならない様にSkip
        rp.AddField(3, New CFieldProvider("3"), .Next)
    End With

サンプル2

次に、以下の複雑なテーブルを作成してみましょう。

フィールドは生成した順にデフォルトのタブオーダが振られるということに注意してください。 この例の場合、タブオーダは垂直方向、つまり伝票番号 > 見積番号 > 見積検索 > 取引区分・・・ という順で設定されるようにしたいので、 全体のオリエンテーションはROWとすべきです。 ただし、青枠で囲った部分のオリエンテーションはCOLにしたいとします。 こうした場合、AscendとDescendの組み合わせを使います。

コードは以下のようになります。

    With New CLayoutBuilder(CLayoutBuilder.EOrientation.ROW)
        rp.AddField("caption", New CCaptionFieldProvider(), .Next(3, 1)) '行番号

        rp.AddField("denpyo_no", New CTextFieldProvider("伝票番号"), .Break.Next)
        rp.AddField("mitsumori_no", New CTextFieldProvider("見積番号"), .Next)
        rp.AddField("mitsumori_search", New CButtonFieldProvider("見積検索", "見積検索"), .Next)

        .Break.Ascend()
        rp.AddField("torihiki_kbn", New CTextFieldProvider("取引区分"), .Next)
        rp.AddField("torihiki_nm", New CTextFieldProvider(), .Next) '取引区分名
        .Descend()

        rp.AddField("juchubi", New CTextFieldProvider("受注日"), .Next(1, 2))
        rp.AddField("noki", New CTextFieldProvider("納期"), .Next(1, 2))

        .Break(2).Ascend()
        rp.AddField("tokuisaki", New CTextFieldProvider("得意先"), .Next)
        rp.AddField("tokuisaki_nm", New CTextFieldProvider(), .Next) '得意先名
        .Descend()

        .Ascend()
        rp.AddField("seikyusaki", New CTextFieldProvider("請求先"), .Next)
        rp.AddField("seikyusaki_nm", New CTextFieldProvider(), .Next) '請求先名
        .Descend()

        .Ascend()
        rp.AddField("nounyusaki", New CTextFieldProvider("納入先"), .Next)
        rp.AddField("nounyusaki_nm", New CTextFieldProvider(), .Next) '納入先名
        .Descend()

        .Break(2).Ascend()
        rp.AddField("tanto", New CTextFieldProvider("担当者"), .Next)
        rp.AddField("tanto_nm", New CTextFieldProvider(), .Next) '担当者名
        .Descend()

        .Ascend()
        rp.AddField("bumon", New CTextFieldProvider("部門"), .Next)
        rp.AddField("bumon_nm", New CTextFieldProvider(), .Next) '部門名
        .Descend()

        .Ascend()
        rp.AddField("soko", New CTextFieldProvider("倉庫"), .Next)
        rp.AddField("soko_nm", New CTextFieldProvider(), .Next) '倉庫名
        .Descend()

        rp.AddField("biko", New CTextFieldProvider("備考"), .Break(2).Next(3, 1))
    End With

フィールドディスクプリタ

レコードプロバイダのAddFieldメソッドは、 フィールドディスクプリタというオブジェクトを返します。 フィールドディスクプリタは、フィールドを生成するために必要なオブジェクトや、 フィールドの動作を制御するためのいくつかのプロパティを持っています。

フィールドディスクプリタのプロパティを以下に示します。

プロパティ説明
Provider 設定されたフィールドプロバイダ
Layout 設定されたレイアウトのリージョン
Setting 色、アライメント、フォントなどの設定
UserSortable ユーザが見出しフィールドをダブルクリックすることで
ソート可能とするかを設定・取得します
Comparer ソートに利用されるコンペアラを設定・取得します
CreateCaption 見出しフィールドを生成するかを設定・取得します
デフォルトはTrueです
MergeCaption 見出しを生成するときにマージするフィールドのキーを設定・取得します
指定するキーは、隣のフィールドのものである必要はありません
隣のフィールドでない場合、間にあるフィールドの見出しは全て上書きされます
マージによって上書きされるフィールドは、自身の見出しフィールドが生成されないように
CreateCaptionをFalseとしてください

フィールドディスクリプタは、AddFieldの戻り値として得る以外に、FieldDescsプロパティから得る方法もあります。

    RecordProvider.FieldDesc(key)

レコードプロバイダを使わずに、直接レコードのAddFieldを利用してフィールドを作成した場合も、 内部的にフィールドディスクプリタが生成されてからフィールドが作られます。 つまり、フィールドは常にフィールドディスクリプタを元にして作られます。

フィールドは自身を生成する時に利用されたフィールドディスクリプタをDescというプロパティに保持しています。 例えば以下のように書くと、フィールドから対応するフィールドプロバイダを得ることができます。

    fieldprovider = Field.Desc.Provider

見出しレコードの制御

通常、見出しレコードを作成するにはCreateCaptionメソッドを使用します。 CreateCaptionはContentが持つフィールドディスクプリタを元にして、 同じレイアウトになるように見出しを生成します。 しかし、先ほどの例ではContentと見出しのレイアウトが一部異なっていました。 たとえば、取引区分と取引区分名はContentでは分かれていますが、見出しではマージされています。

取引区分と取引区分名の見出しをマージするには、以下のように書きます。

    .Break.Ascend()
    rp.AddField("torihiki_kbn", New CTextFieldProvider("取引区分"), .Next) _
      .MergeCaption = "torihiki_nm"
    rp.AddField("torihiki_nm", New CTextFieldProvider(), .Next) _
      .CreateCaption = False '取引区分名
    .Descend()

CreateCaptionメソッドのオーバーロード

CreateCaptionメソッドには、以下のオーバーロードがあります。

    Table.CreateCaption(halign)
    Table.CreateCaption(halign, rp,...)

CreateCaptionメソッドが生成する見出しフィールドには、 元となったフィールドディスクプリタの持つSettingがコピーされて設定されます。 ただし、水平方向アライメントだけは、引数halignで指定することができます。

引数rpには、見出しレコードの元になるレコードプロバイダを指定できます。 rpは可変個引数となっており、指定された全てのrpに対応する見出しレコードが 階層構造となって生成されます。

見出しフィールドのキー

CreateCaptionで作成される見出しフィールドのキーは、対応するフィールドディスクリプタのキーを CCaptionKeyというラッパークラスで包んだオブジェクトになります。 ラッパークラスを用いる理由は、(主にイベントハンドラ内で) あるフィールドが明細フィールドなのか見出しフィールドなのかを、 キーの型で区別可能とするためです。

CCaptionKeyオブジェクトを生成するためのメソッドCaptionKeyが、UTableのsharedメソッドとして定義されています。

    UTable.CaptionKey(key)

keyにはラップするキーの値を渡します。

CaptionRecordメソッド

CreateCaptionメソッドでは生成できないような特殊な見出しを作成したい場合は、 直接HeaderContentへレコードとフィールドを追加してください。 この際、テーブルのCaptionRecordメソッドを用いると便利です。

  record = Table.CaptionRecord()

このメソッドはHeaderContentの0番目のレコードを返します。もしレコードが無ければ作成して返します。

見出しフィールドを独自に定義する場合は、キーをCaptionKeyメソッドで生成してください。 そのときラップされるキーは、対応するフィールドと一致させてください。 こうすることで見出しのダブルクリックによるソート機能が正しく動作するようになります。

サンプルとして、以下の表を作成します。明細は1行であるのに対し、見出しは2行で成り立っています。

ソースコードは以下のようになります。

    Dim rp As New UTable.CRecordProvider
    With New CLayoutBuilder
        rp.AddField("0", New CFieldProvider, .Next)
        rp.AddField("1", New CFieldProvider, .Next)
        rp.AddField("2", New CFieldProvider, .Next)
    End With
    Me.Table.Content.SetRecordProvider(rp)
   
    Dim cap As UTable.CRecord = Me.Table.CaptionRecord
    With New CLayoutBuilder
        cap.AddField(UTable.CaptionKey("_"), New CCaptionFieldProvider, .Next(1, 3))
        cap.AddField(UTable.CaptionKey("1"), New CCaptionFieldProvider("1"), .Break.Next)
        cap.AddField(UTable.CaptionKey("2"), New CCaptionFieldProvider("2"), .Next)
        cap.AddField(UTable.CaptionKey("3"), New CCaptionFieldProvider("3"), .Next)
    End With

    '見出しと明細のレイアウトが違うので、FocusCaptionBackColorは無効にする
    Me.Table.Setting.FocusCaptionBackColor = Color.Transparent

    Using Me.Table.RenderBlock
        For i As Integer = 1 To 10
            Me.Table.Content.AddRecord()
        Next
    End Using

階層構造

以下の図のように階層構造を持ったテーブルもレコードプロバイダから作成することができます。

階層構造を定義する最も低レベルな方法は、レコードのCreateChildメソッドを呼ぶことです。 このメソッドは、作成された子コンテントを返します。 作成済みの子コンテントを得るには、レコードのChildプロパティを用います。

  subContent = Record.CreateChild()
  subContent = Record.Child

レコードプロバイダのSetChildRecordProviderで子コンテント用のレコードプロバイダを設定しておくと、 レコードが追加されたときに、自動的にCreateChildが呼ばれます。 さらに、作成された子コンテントにレコードプロバイダが設定されます。 上図のテーブルを作成するためのレコードプロバイダは以下のようにして作成します。

    Dim rp1 As New UTable.CRecordProvider
    With New CLayoutBuilder
        rp1.AddField("0", New CNarrowChildFieldProvider, .Next)
        rp1.AddField("1", New CTextFieldProvider, .Next)
    End With
    Dim rp2 As New UTable.CRecordProvider
    With New CLayoutBuilder
        rp2.AddField("2", New CTextFieldProvider, .Skip.Next)
    End With
    rp1.SetChildRecordProvider(rp2)
    Table.Content.SetRecordProvider(rp1)

このレコードプロバイダが設定されている状態でCreateCaptionを行うと、 デフォルトでは、rp1、rp2両方に対応するレコードが生成されます。 rp1に対応する見出しのみが生成されるようにするには、 以下のように書きます。

    Table.CreateCaption(UTableEx.EHAlign.DEFAULT, rp1)

各レコードが5個ずつ子レコードを持つようにするには、以下のように書きます。

    For i As Integer = 1 To 10
        Dim r As UTable.CRecord = Me.Table.Content.AddRecord
        For j As Integer = 1 To 5
            r.Child.AddRecord()
        Next
    Next

次へ    ドキュメントのトップ / ホーム


Copyright (c) 2009, SystemBase Co.,Ltd.
All rights reserved.