DBGridEhのインジケータにチェックボックスを実装し全選択を制御する方法

DBGridEhでインジケータ領域に動的なチェックボックスを表示し、全選択機能を適切に動作させるための設定と実装方法について解説します。

基本的な設定

チェックボックスを表示して操作可能にするには、以下のプロパティを設定します。

  • IndicatorOptions に以下を含めます:
    • gioShowRowIndicatorEh:行インジケータ(矢印)を表示
    • gioShowRecNoEh:レコード番号を表示
    • gioShowRowselCheckboxesEh:チェックボックスを表示
  • OptionsdgMultiSelect を含めます。これによりチェックボックスのオン/オフが可能になります。

選択行の取得

チェックされた行のデータを処理するには、SelectedRowsをループしてブックマークでデータセットのカーソルを移動します。

var
  RowIdx: Integer;
begin
  for RowIdx := 0 to Pred(MyDBGrid.SelectedRows.Count) do
  begin
    MyDBGrid.DataSource.DataSet.Bookmark := MyDBGrid.SelectedRows[RowIdx];
    // カーソル移動後のデータ処理
  end;
end;

全選択および選択解除

コードから全選択や選択解除を行う場合は、以下のメソッドを使用します。

// 全レコードを選択(SelectionType = gstRecordBookmarks)
MyDBGrid.Selection.Rows.SelectAll;

// 選択を全解除
MyDBGrid.Selection.Clear;

※全選択において、Selection.SelectAllを使用するとSelectionTypegstAllとなりますが、後述の理由によりSelection.Rows.SelectAllを使用することが重要です。

インジケータタイトルクリック時の全選択問題と対策

DBGridEhのデフォルト設定では、AllowedSelections[gstRecordBookmarks, gstRectangle, gstColumns, gstAll]が含まれています。この状態でグリッド左上のインジケータタイトルをクリックすると全選択が動作しますが、データをループで処理することができなくなります。

原因はDBGridEhの内部処理にあります。インジケータタイトルのマウスダウンイベントでは、AllowedSelectionsの判定順序に依存しており、gstAllが優先的に実行されるためです。

// 内部ロジックの抜粋
if (dgMultiSelect in Options) and DataLink.Active and
   ([gstRecordBookmarks, gstAll] * AllowedSelections <> []) then
begin
  if Selection.SelectionType <> gstNon then
    Selection.Clear
  else if gstAll in AllowedSelections then
    Selection.SelectAll       // こちらが先に評価される
  else if gstRecordBookmarks in AllowedSelections then
    Selection.Rows.SelectAll; // ブックマークベースの選択
end;

gstAllで選択された状態ではブックマークが設定されず、データセットのカーソル移動ができません。この問題を解決するには、AllowedSelectionsプロパティからgstAllを除外します。

AllowedSelections = [gstRecordBookmarks, gstRectangle, gstColumns] // gstAllを削除

クリック時の選択解除を防ぐ

gstAllを削除したことでインジケータタイトルによる全選択は機能しますが、デフォルト設定のままではグリッドの他の領域をクリックした際に選択状態が解除されやすくなります。

これを防ぐためには、OptionsEhプロパティからdghClearSelectionを除外します。

// dghClearSelectionを含めないように設定
OptionsEh = [...] // dghClearSelectionを除外

タグ: Delphi DBGridEh VCL

7月19日 17:37 投稿