以下は、cxGridコンポーネントでマスター/詳細構造を実装した際の表示イメージです。左側の展開アイコン(+/-)により、各マスター行に対応する詳細データの表示・非表示を切り替えられます。
設計構造としては、2つのレベル(Level)と2つのDBテーブルを用意します。例えば、「TV廃棄リスト」をマスターテーブル、「TV在庫照会」を詳細テーブルとして関連付けます。この構成により、階層的なデータ表示が可能になります。
まず、それぞれのデータセットを準備し、業務要件に応じたSQLクエリを記述します。その後、マスターと詳細の関連付けを行います。この部分はネット上でも情報が少なく、特に画像付き解説が少ないので、ここでは具体的な設定手順を詳しく説明します。
マスターテーブルの設定
「TV廃棄リスト」を選択し、プロパティパネルで KeyFieldNames を設定します。このフィールドはマスターテーブル内で一意である必要があります。重複値があるとIDEが不安定になる可能性があります(例:Delphi 10.3.3)。
詳細テーブルの設定
「TV在庫照会」を選択し、マスターテーブルとの関連フィールド名を一致させます。詳細テーブル側には一意キーがなくても問題ありませんが、KeyFieldNames は空のままでも構いません。ただし、関連フィールド(例:「部品コード」)は両テーブルで同じ名前・型である必要があります。
データが正しく表示されない場合の対処法
設定後も詳細データが1件しか表示されない、または表示されない場合は、SQL文に ORDER BY 関連フィールド を追加してください。これは内部データバインディングの安定性を確保するために重要です。
詳細データの取得とレコード数のカウント
詳細テーブルのレコード数を取得するには、以下のコードを使用します:
DetailCount := MasterView.ViewData.Rows[i].AsMasterDataRow.ActiveDetailGridView.DataController.RecordCount;
詳細テーブル内の特定セルの値を取得するには:
V := TcxGridDBTableView(MasterView.ViewData.Rows[i].AsMasterDataRow.ActiveDetailGridView).ViewData.Rows[j].Values[k];
実装例:詳細データを抽出してメモ欄に出力
procedure TForm1.Button1Click(Sender: TObject);
var
i, j, k, DetailCount: Integer;
s: string;
v: Variant;
begin
Memo1.Clear;
for i := 0 to MasterView.DataController.RowCount - 1 do begin
DetailCount := MasterView.ViewData.Rows[i].AsMasterDataRow.ActiveDetailGridView.DataController.RecordCount;
Memo1.Lines.Append('');
// マスター行の内容出力
s := '';
for k := 0 to 2 do begin
v := MasterView.ViewData.Rows[i].Values[k];
if VarIsNull(v) then
s := s + '; '
else
s := s + string(v) + '; ';
end;
Memo1.Lines.Append(s);
// 詳細行の内容出力
for j := 0 to DetailCount - 1 do begin
s := ' ';
for k := 0 to 3 do begin
if k = 1 then Continue; // 特定カラムをスキップ
with TcxGridDBTableView(MasterView.ViewData.Rows[i].AsMasterDataRow.ActiveDetailGridView) do
v := ViewData.Rows[j].Values[k];
if VarIsNull(v) then
s := s + '; '
else
s := s + string(v) + '; ';
end;
Memo1.Lines.Append(s);
end;
Memo1.Lines.Append(' 詳細レコード数: ' + IntToStr(DetailCount));
end;
end;
条件付き展開:詳細データがある場合のみ展開を許可
DataController.OnDetailExpanding イベントを使用して、詳細データが存在しない行の展開を抑制できます:
procedure TForm1.MasterTableDataControllerDetailExpanding(
ADataController: TcxCustomDataController;
ARecordIndex: Integer;
var AAllow: Boolean);
var
DetailRowCount: Integer;
begin
DetailRowCount := MasterView.ViewData.Rows[ARecordIndex]
.AsMasterDataRow.ActiveDetailGridView.DataController.RecordCount;
AAllow := DetailRowCount > 0; // 詳細データが1件以上ある場合のみ展開を許可
end;
詳細セルのダブルクリックでマスター行を更新し、詳細を折りたたむ
procedure TForm1.DetailViewCellDblClick(
Sender: TcxCustomGridTableView;
ACellViewInfo: TcxGridTableDataCellViewInfo;
AButton: TMouseButton;
AShift: TShiftState;
var AHandled: Boolean);
var
CurrentRow, SupplierIDCol, PurposeCol: Integer;
RecordID, SupplierID, Purpose: string;
begin
CurrentRow := ACellViewInfo.RecordViewInfo.Index;
SupplierIDCol := ColSupplier.Index;
PurposeCol := ColPurpose.Index;
RecordID := DataSource.FieldByName('recordid').AsString;
Purpose := TcxGridDBTableView(MasterView.ViewData.Rows[MasterView.Controller.FocusedRowIndex]
.AsMasterDataRow.ActiveDetailGridView).ViewData.Rows[CurrentRow].Values[PurposeCol];
SupplierID := TcxGridDBTableView(MasterView.ViewData.Rows[MasterView.Controller.FocusedRowIndex]
.AsMasterDataRow.ActiveDetailGridView).ViewData.Rows[CurrentRow].Values[SupplierIDCol];
with UpdateQuery do begin
Close;
SQL.Text := Format('UPDATE 廃棄テーブル SET 供給元=%s, 用途=%s WHERE recordid=%s',
[SupplierID, QuotedStr(Purpose), RecordID]);
ExecSQL;
end;
DataSource.Refresh; // データ再読み込み
MasterView.ViewData.Collapse(True); // 全ての詳細行を折りたたむ
end;
展開・折りたたみ操作の共通コード
// 全行展開
MasterView.ViewData.Expand(True);
// 全行折りたたみ
MasterView.ViewData.Collapse(True);
// 現在選択中の行のみ展開
MasterView.ViewData.Rows[MasterView.DataController.FocusedRowIndex].Expand(True);
// 現在選択中の行のみ折りたたみ
MasterView.ViewData.Rows[MasterView.DataController.FocusedRowIndex].Collapse(True);
列のプロパティ動的設定と取得
// 列の編集タイプを動的に変更
DetailViewColumn1.PropertiesClass := TcxSpinEditProperties;
// 表示フォーマットを設定
TcxSpinEditProperties(DetailViewColumn1.Properties).DisplayFormat := '0.00';
// 設定済みのプロパティ値を取得
ShowMessage(TcxSpinEditProperties(DetailViewColumn1.Properties).DisplayFormat);
利用可能なエディットプロパティクラス
- TcxTextEditProperties
- TcxDateEditProperties
- TcxCalcEditProperties
- TcxCheckBoxProperties
- TcxSpinEditProperties
- ...その他多数(IDEの補完機能で確認可能)
グリッド列の全削除と再生成
// 全列削除
IcxCustomGridDataController(GridTableView.DataController).DeleteAllItems;
// 自動再生成(false = 表示位置を保持しない)
IcxCustomGridDataController(GridTableView.DataController).CreateAllItems(False);