4Dではリストボックスを階層表示にするよう指定することができます。階層リストボックスは左の列が階層状に表示されます。このタイプの表示方法は、繰り返される値や、階層に依存するデータの表示などに適用できます (国/地域/都市など)。
配列タイプのリストボックスのみを階層にできます。
階層リストボックスはデータを表示する特別な方法ですが、データの構造 (配列) は変更しません。階層リストボックスは通常のリストボックスと全く同じ方法で管理されます。
階層リストボックスと指定するには、3つの方法があります:
この節では4Dのフォームエディターで階層リストボックスを作成する方法と、実行時にそれがどのように動作するかについてその基礎に加えて、その管理について説明しています(On Expand やOn Collapse フォームイベントを使用してセレクションやブレークを管理する方法等)。
プロパティリストの"階層"テーマで階層モードを設定できます。詳細はリストボックス特有のプロパティを参照してください。
フォームエディターのリストボックスの列エリアを右クリックして表示されるコンテキストメニューから、階層を作成や階層をキャンセルコマンドにアクセスできます。
フォームエディター中で配列タイプのリストボックスオブジェクトの一番目から任意の数の列を選択すると、階層を作成コマンドがコンテキストメニューから利用できるようになります:

このコマンドを選択すると、以下のアクションが実行されます:
- そのオブジェクトのプロパティリストで"階層リストボックス"オプションが選択されます。
- その列の変数が階層を指定するために使用されます。既に設定されていた内容は新しい内容で置き換えられます。
- (最初の列を除き) 選択された列はリストボックス内に表示されなくなります。
例: 左から国、地域、都市、人口列が設定されたリストボックスがあります。国、地域、都市が (下図の通り) 選択され、コンテキストメニューから階層を作成を選択すると、最初の列に3レベルの階層が作成され、二番目と三番目の列は取り除かれます。人口列が二番目になります:
階層リストボックスとして定義されたリストボックスで最初の列を選択すると、階層をキャンセルコマンドを使用できます。このコマンドを選択すると以下のアクションが実行されます:
- そのオブジェクトの"階層リストボックス"オプションの選択が解除されます。
- 2番目以降の階層レベルが削除され、通常の列としてリストボックスに追加されます。
階層リストボックスを含むフォームが最初に開かれる際、デフォルトですべての行が展開されています。
配列中で値が繰り返されていると、ブレーク行と階層"ノード"が自動でリストボックスに追加されます。例えばリストボックスに都市に関する4つの配列が含まれていて、それぞれ国、地域、都市名、人口データが含まれているとします:

リストボックスが階層形式で表示されると (先頭3つの配列が階層化されている場合)、以下のように表示されます:

階層を正しく構築するためには、事前に配列をソートしなければなりません。例えば配列中にデータがAAABBAACCの順で含まれていると、階層は以下のようになります:
> A
> B
> A
> C
階層"ノード"を展開したり折りたたんだりするには、ノード上をクリックします。ノード上をAlt+クリック (Windows) または Option+クリック (macOS) すると、すべてのサブ要素が同時に展開されたり折りたたまれたりします。これらの動作はLISTBOX EXPAND および LISTBOX COLLAPSE コマンドを使用することでプログラミングでも実行可能です。
階層リストボックスに日付や時間型の値を表示する際、それらは標準フォーマットで表示されます:
- 日付はShort system formatで表示されます (例えば2009年5月30日の場合、日本語システム上では09/05/30と表示されます)。
- 時間もShort system formatで表示されます (システムパラメターに基づき"12:15:30"または"12:15"で表示されます)。
階層モードのリストボックスにおいて、(リストボックス列のヘッダーをクリックして実行される) 標準の並び替えは常に以下のように行われます:
- まず階層列 (一番目の列) のすべてのレベルが自動で昇順にソートされます。
- 次にクリックされた列の値を使用して昇順または降順にソートが実行されます。
- すべての列が同期されます。
- その後の非階層列のソート時には、一番目の最後のレベルのみがソートされます。この列のソートはそのヘッダーをクリックすることで行えます。
まだソートされていない以下のリストボックスがあります:

"Population"ヘッダーをクリックして人口に基づき昇順あるいは降順でソートを行うと、データは以下のように表示されます:

通常のリストボックスと同様、リストボックスの"ソート可"オプションの選択を解除することで標準のソートメカニズムを無効にし、プログラムでソートを管理できます。
階層リストボックスはノードの展開/ 折りたたみ状態により、スクリーン上に表示される行数が変わります。しかし配列の行数が変わるわけではありません。表示が変わるだけでデータに変更はありません。
この原則を理解することは重要です。階層リストボックスに対するプログラムによる管理は常に配列データに対して行われるのであり、表示されたデータに対して行われるわけではないからです。特に、自動で追加されるブレーク行は、表示オプション配列では考慮されません (後述参照)。
例として以下の配列を見てみましょう:

これらの配列が階層的に表示されると、2 つのブレーク行が追加されるため、"Quimper" 行は2 行目ではなく4 行目に表示されます:

階層であってもなくても、リストボックスにどのようにデータが表示されているかにかかわらず、"Quimper" が含まれる行を太字にしたい場合はステートメントStyle{2} = bold を使用しなければなりません。配列中の行の位置のみが考慮されます。
この原則は以下のものを管理する内部的な配列に適用されます:
例えばRennesを含む行を選択したい場合、以下のように書きます:
->MyListbox{3}:=True
非階層表示:

階層表示:

注: 親が折りたたまれているために行が隠されていると、それらは選択されなくなります。(直接あるいはスクロールで) 表示されている行のみを選択できます。言い換えれば行を選択かつ隠された状態にすることはできません。
選択と同様、LISTBOX GET CELL POSITION コマンドは階層リストボックスと非階層リストボックスにおいて同じ値を返します。つまり以下の両例題で、LISTBOX GET CELL POSITION は同じ位置 (3;2) を返します。
非階層表示:

階層表示:

サブ階層のすべての行が隠されているとき、ブレーク行は自動で隠されます。先の例題で1から3行目までが隠されていると、"Brittany"のブレーク行は表示されません。
ユーザがブレーク行を選択すると、LISTBOX GET CELL POSITIONは 対応する配列の最初のオカレンスを返します。以下のケースで:

LISTBOX GET CELL POSITIONは (2;4) を返します。プログラムでブレーク行を選択するにはLISTBOX SELECT BREAKコマンドを使用する必要があります。
ブレーク行はリストボックスのグラフィカルな表示 (スタイルやカラー) を管理する内部的な配列では考慮されません。しかしオブジェクトのグラフィックを管理する
オブジェクト(フォーム)テーマのコマンドを使用してブレーク行の表示を変更できます。階層を構成する配列に対して、適切なコマンドを実行します。
以下のリストボックスを例題とします (割り当てた配列名は括弧内に記載しています):
非階層表示:

階層表示:

階層モードではtStyleやtColors配列で変更されたスタイルは、ブレーク行に適用されません。ブレークレベ ルでカラーやスタイルを変更するには、以下のステートメントを実行します:
注: このコンテキストでは、配列は割り当てられたオブジェクトがないため、配列変数を使用したシンタックスのみがオブジェクトプロパティコマンドで動作します。
結果:

On Expand や On Collapse フォームイベントを使用して階層リストボックスの表示を最適化できます。
階層リストボックスはその配列の内容から構築されます。そのためこれらの配列すべてがメモリにロードされる必要があります。大量のデータから (SELECTION TO ARRAYを使用して) 生成される配列を元に階層リストボックスを構築するには、表示速度だけでなくメモリ利用量の観点からも困難が伴います。
On Expand と On Collapse フォームイベントを使用してこの制限を回避できます。例えばユーザーのアクションを元に階層の一部だけを表示したり、必要に応じて配列をロード/アンロードできます。
これらのイベントのコンテキストでは、LISTBOX GET CELL POSITIONコマンドは、行を展開/折りたたむためにユーザーがクリックしたセルを返します。
この場合、開発者がコードを使用して配列を空にしたり値を埋めたりしなければなりません。実装する際注意すべき原則は以下のとおりです: