从 TDBGrid 和 cxGrid 迁移到 sgcGrid

sgcGrid 是一个 VCL 数据网格 TsgcVCLGrid,可绑定到任何 TDataSet,并在每个版本中提供分组、汇总、筛选、查找面板、分带和已保存的布局。本套件把您使用的每个 TDBGrid 和 cxGrid 成员对应到 sgcGrid 中的对应项,展示来自可编译演示的代码,并如实列出无法对应的部分。

两个起点,一个网格

使用标准 TDBGrid 的 Delphi VCL 团队,以及正在评估是否续订订阅的 DevExpress cxGrid 团队。

从 TDBGrid 迁移

标准 VCL TDBGrid 可以显示和编辑数据集,仅此而已。它没有筛选行、列筛选、分组、页脚或分组汇总、查找面板、分带、最佳列宽,也没有布局的保存和加载。这些功能要么自己写代码,要么借助第三方网格。sgcGrid 把它们全部集成在一个控件中,并绑定到您现有的数据集。

从 cxGrid 迁移

DevExpress cxGrid(ExpressQuantumGrid)是一款功能广泛且成熟的网格。主要把它当作带分组、汇总、筛选和已保存布局的表格视图来使用的团队,可以用 sgcGrid 覆盖这些功能,并获得完整源代码,同时放弃一份远不止网格的订阅。

目前网格的成本:2026-10-20,DevExpress VCL 价格表提供三种订阅,全部包含 ExpressQuantumGrid 控件。最低的是 Express QuantumPack,价格为 999.99 美元,VCL Subscription 为 1,699.99 美元。在 2025 年 9 月 18 日的 Delphi-PRAXiS 帖子中,有用户报告他的 cxGrid 订阅从 400 美元涨到 550 美元,另一位成员引用了 DevExpress 的公告,称新的 Express GridPack 许可证不再出售(现有订阅用户仍可续订)。sgcGrid 按开发者授权,价格从 €199 起,附带完整源代码和一年更新,同时也包含在每个 sgcUI 版本中。

一个控件,绑定任何 TDataSet

一个 TsgcVCLGrid 和一个 TsgcGridSource_DataSet,设置 DataSet、Grid 和 KeyField。数据集事件会让网格保持同步。

每个版本都有

按 FieldName 匹配的设计列、查阅字段、单元格、行和多行选择、行头、自定义绘制、Ctrl+C、分组面板、页脚和分组汇总、筛选行、Excel 风格的列筛选、查找面板、分带、最佳列宽,以及 JSON 布局的保存和加载。

仅限注册版

写回数据集的双向编辑(WriteBack)、光标同步(SyncCursor)、插入、删除、粘贴和撤销、卡片视图(ViewStyle)以及面向超大表的服务器模式。试用版包含这些功能供评估。社区版构建不包含它们:演示在社区版中仍可编译,其网格为只读。

TDBGrid 成员与 sgcGrid 对应项

下面每个 sgcGrid 名称都在随产品提供的源代码中,演示用到的名称都可以编译。

TDBGrid sgcGrid 版本
TDBGridTsgcVCLGrid(单元 sgcGrid_VCL)全部
DataSourceTsgcGridSource_DataSet:DataSet、Grid、KeyField,然后 Active := True(单元 sgcGrid_Source_DataSet)全部
Columns, TColumn.FieldNameColumns、Columns[i].FieldName。设计列会被保留并按 FieldName 匹配;没有列时,AutoColumns 会创建它们全部
Title.Caption, Width, VisibleColumns[i].Caption, Width, Visible全部
TColumn.ReadOnlyColumns[i].Editable全部(编辑:注册版)
TColumn.PickList、查阅字段下拉框Columns[i].PickList;对于查阅字段,数据源会从 LookupDataSet 填充列表全部(写入值:注册版)
TField.DisplayFormatColumns[i].DisplayFormat全部
ReadOnly, Options dgEditingTsgcVCLGrid.ReadOnly(默认 True)和 TsgcGridSource_DataSet.WriteBack注册版
dgRowSelectSelectionMode := gsmRow(不设置时为 gsmCell)全部
dgMultiSelect, SelectedRowsSelectionMode := gsmMultiRow; SelectedRows, SelectedRowCount, GetSelectedKeys, RowSelected[]全部
dgIndicatorRowHeader := [grhIndicator](还有 grhNumbers、grhCheckBox)全部
dgColLines, dgRowLinesGridLinesV, GridLinesH全部
当前记录跟随网格TsgcGridSource_DataSet.SyncCursor注册版
OnDrawColumnCell, DefaultDrawColumnCell带 aDefaultDraw 的 OnCustomDrawCell;仅处理颜色时,用 OnGetCellStyle 或 FormatRules全部
OnTitleClickOnHeaderClick全部
Ctrl+C(自定义代码)内置(Ctrl+C、Ctrl+Ins);文本来自 SelectionToText全部
Insert 和 Ctrl+Del 键AllowInsert, AllowDelete, InsertRow, DeleteSelectedRows, OnBeforeDelete注册版

cxGrid 成员与 sgcGrid 对应项

cxGrid 名称是 DevExpress 的标识符,仅供参考。

cxGrid sgcGrid 版本
TcxGridDBTableView, DataController.DataSourceTsgcVCLGrid 和 TsgcGridSource_DataSet全部
TcxGridDBColumn.DataBinding.FieldNameColumns[i].FieldName全部
TcxGridDBColumn.GroupIndexColumns[i].GroupIndex; GroupBy(['Field']), ClearGrouping, GroupCount全部
OptionsView.GroupByBoxShowGroupPanel全部
DataController.Groups.FullExpand, FullCollapseExpandAll, CollapseAll全部
OptionsView.FooterShowFooter全部
DataController.Summary.FooterSummaryItems (skSum, skCount, skAverage, skMin, skMax)Columns[i].SummaryType(gsuSum、gsuCount、gsuAverage、gsuMin、gsuMax)、SummaryFormat;值来自 FooterSummary(aCol)、FooterSummaryText(aCol);SummaryScope全部
DataController.Summary.DefaultGroupSummaryItemsGroupSummaries,使用分组中的列 SummaryType全部
FilterRow.VisibleShowFilterRow, Columns[i].FilterRowOperator全部
列筛选下拉框ShowFilterButtons, ShowFilterPopup(aCol), ClearColumnFilter(aCol), ClearColumnFilters, OnFilterChange全部
FindPanel.DisplayModeShowFindPanel, FindText, FindNext, FindPrevious, FindOnlyMatches全部
TcxGridDBBandedTableView.Bands, Column.Position.BandIndexBands (Caption, ParentBand, Visible), Columns[i].Band全部
ApplyBestFitBestFitColumns, BestFitColumn(aCol), BestFitOnDblClick, BestFitSampleRows全部
StoreToIniFile, RestoreFromIniFileSaveLayoutToFile、LoadLayoutFromFile(JSON),也可以保存到字符串或流、从字符串或流加载;使用 AutoSaveLayout 和 LayoutStorageKey 可自动保存全部
OptionsCustomize.ColumnMovingColumnMoving全部
列自定义对话框ShowColumnChooser全部
OnCustomDrawCellOnCustomDrawCell全部
TcxGridDBCardView(第二个视图)在同一个网格上设置 ViewStyle := gvsCard,以及 CardOptions(CaptionField、CardWidth、CardHeight、ShowFieldCaptions)注册版

代码,来自可编译的演示

每个片段都复制自 MigrateFromDBGrid 演示,该演示可用 Delphi 7 和 Delphi 13(Win32 和 Win64)编译。注释中写明了它所替代的 TDBGrid 或 cxGrid 代码。

绑定:DataSource 变成 TsgcGridSource_DataSet

迁移前:带 DataSource := dsProducts 的 TDBGrid。迁移后:窗体上的数据源组件。

frmMain.dfm
object SourceDB: TsgcGridSource_DataSet
  DataSet = cdsProducts
  Grid = GridDB
  KeyField = 'ID'
  Left = 280
  Top = 520
end

TDBGrid 选项变成属性

迁移前:带 dgEditing、dgRowSelect、dgMultiSelect 和 dgIndicator 的 Options。迁移后:

frmMain.pas
procedure TFormMain.chkOptionsClick(Sender: TObject);
begin
  // TDBGrid.ReadOnly / Options dgEditing -> ReadOnly
{$IFDEF SGC_GRID_EDIT}
  GridDB.ReadOnly := not chkEditing.Checked;
{$ENDIF}
  // dgMultiSelect -> gsmMultiRow, dgRowSelect -> gsmRow, neither -> gsmCell
  if chkMultiSelect.Checked then
    GridDB.SelectionMode := gsmMultiRow
  else if chkRowSelect.Checked then
    GridDB.SelectionMode := gsmRow
  else
    GridDB.SelectionMode := gsmCell;
  // dgIndicator -> RowHeader [grhIndicator] (grhNumbers, grhCheckBox too)
  if chkIndicator.Checked then
    GridDB.RowHeader := [grhIndicator]
  else
    GridDB.RowHeader := [];
end;

OnDrawColumnCell 变成 OnCustomDrawCell

迁移前:读取 Column.FieldName 和字段值的 OnDrawColumnCell。迁移后:aCol 是 Columns 的索引,aRow 是 Data 的视图行(CS_LOW_STOCK 是演示中的常量)。

frmMain.pas
procedure TFormMain.GridDBCustomDrawCell(Sender: TObject; aCanvas: TsgcUICanvas;
  aRow, aCol, aLeft, aTop, aRight, aBottom: Integer;
  aState: TsgcGridCellDrawStates; var aDefaultDraw: Boolean);
begin
  // TDBGrid.OnDrawColumnCell: Column.FieldName and Field.AsInteger.
  // sgcGrid: aCol is the Columns index, aRow the view row of Data. The
  // background is painted already; aDefaultDraw False would skip the text
  if (aRow < 0) or (aRow >= GridDB.Data.ViewCount) or
    (GridDB.Columns[aCol].FieldName <> 'Qty') then
    Exit;
  if StrToIntDef(VarToStr(GridDB.Data.Cells[aRow, aCol]), 0) < CS_LOW_STOCK
  then
  begin
    // a red marker at the left edge of a low stock cell
    aCanvas.BeginPath;
    aCanvas.Rectangle(aLeft, aTop + 4, aLeft + 4, aBottom - 4);
    aCanvas.ClosePath;
    aCanvas.FillPath($FFDC2626);
  end;
end;

写回、光标同步和分组

迁移前:TDBGrid 上的 dgEditing,以及拖到 cxGrid GroupByBox 的列。迁移后:

frmMain.pas
procedure TFormMain.FormCreate(Sender: TObject);
begin
  DoCreateData;
  // TDBGrid: DataSource := dsProducts. sgcGrid: a TsgcGridSource_DataSet
  // with DataSet, Grid and KeyField (set on the form). The grid columns are
  // designed on the form like TDBGrid.Columns, matched by FieldName
{$IFDEF SGC_GRID_EDIT}
  // TDBGrid dgEditing posts edits to the dataset: WriteBack. The current
  // record follows the focused row and back: SyncCursor
  SourceDB.WriteBack := True;
  SourceDB.SyncCursor := True;
{$ELSE}
  chkEditing.Checked := False;
  chkEditing.Enabled := False;
  chkEditing.Caption := 'Editing (Registered edition)';
  GridDB.ReadOnly := True;
{$ENDIF}
  SourceDB.Active := True;
  SourceCx.Active := True;
  chkOptionsClick(nil);
  // cxGrid: drag a column to the GroupByBox. sgcGrid: ShowGroupPanel, and
  // GroupBy from code (cxGridDBColumn.GroupIndex is Columns[i].GroupIndex)
  GridCx.GroupBy(['Category']);

设计时的 cxGrid 表格视图功能

迁移前:页脚汇总项、分组框、筛选行、查找面板和分带表格视图。迁移后:窗体上的列属性和网格属性。

frmMain.dfm
Columns = <
  item
    FieldName = 'ID'
    Caption = 'ID'
    DataType = gdtInteger
    Width = 60
    SummaryType = gsuCount
    Band = 0
  end
  item
    FieldName = 'Product'
    Caption = 'Product'
    Width = 220
    Band = 0
  end
  item
    FieldName = 'Category'
    Caption = 'Category'
    Width = 140
    Band = 0
  end
  item
    FieldName = 'Price'
    Caption = 'Price'
    DataType = gdtFloat
    Width = 110
    DisplayFormat = '#,##0.00'
    SummaryType = gsuAverage
    SummaryFormat = '#,##0.00'
    Band = 1
  end
  item
    FieldName = 'Qty'
    Caption = 'Qty'
    DataType = gdtInteger
    Width = 90
    SummaryType = gsuSum
    Band = 1
  end>
FormatRules = <>
ShowFooter = True
ShowGroupPanel = True
GroupSummaries = True
ShowFilterButtons = True
ShowFilterRow = True
ShowFindPanel = True
Bands = <
  item
    Caption = 'Product'
  end
  item
    Caption = 'Stock and price'
  end>

最佳列宽、布局和卡片视图

迁移前:ApplyBestFit、StoreToIniFile、RestoreFromIniFile 和 TcxGridDBCardView。迁移后:

frmMain.pas
procedure TFormMain.btnBestFitClick(Sender: TObject);
begin
  // cxGridDBTableView.ApplyBestFit -> BestFitColumns (BestFitColumn(i) for
  // one column, BestFitOnDblClick for the header divider)
  GridCx.BestFitColumns;
end;

function TFormMain.DoLayoutFile: string;
begin
  Result := ExtractFilePath(ParamStr(0)) + 'migratefromdbgrid_layout.json';
end;

procedure TFormMain.btnSaveLayoutClick(Sender: TObject);
begin
  // cxGridDBTableView.StoreToIniFile -> SaveLayoutToFile (JSON: columns,
  // widths, order, sort, grouping, filters, summaries, bands, view)
  GridCx.SaveLayoutToFile(DoLayoutFile);
  DoShowStatus('layout saved to ' + ExtractFileName(DoLayoutFile));
end;

procedure TFormMain.btnLoadLayoutClick(Sender: TObject);
begin
  // cxGridDBTableView.RestoreFromIniFile -> LoadLayoutFromFile
  if GridCx.LoadLayoutFromFile(DoLayoutFile) then
    DoShowStatus('layout loaded')
  else
    DoShowStatus('no saved layout');
end;

procedure TFormMain.chkCardViewClick(Sender: TObject);
begin
{$IFDEF SGC_GRID_ADVANCED}
  // cxGridDBCardView (a second view of the level) -> ViewStyle gvsCard of
  // the same grid, CardOptions for the caption field and the card size
  if chkCardView.Checked then
    GridCx.ViewStyle := gvsCard
  else
    GridCx.ViewStyle := gvsTable;
{$ENDIF}
end;

每个窗体七步

数据层保持不变,只有网格及其选项会变化。

1

放置组件

安装 sgcGrid 软件包,然后在窗体上放置一个 TsgcVCLGrid 和一个 TsgcGridSource_DataSet。

2

指向数据集

把数据源的 DataSet 设为旧网格使用的数据集(网格不再需要 TDataSource),然后设置 Grid 和 KeyField,后者是原位更新和写回所需的唯一字段。

3

重新创建列

添加带 FieldName、Caption、Width、DisplayFormat 和 Editable 的 Columns,或者让 Columns 保持为空,由 AutoColumns 根据字段自动生成。

4

映射选项

dgEditing 对应 ReadOnly 和 WriteBack,dgRowSelect 和 dgMultiSelect 对应 SelectionMode,dgIndicator 对应 RowHeader,当前记录用 SyncCursor。

5

迁移绘制代码

把 OnDrawColumnCell 的代码移到 OnCustomDrawCell,如果只设置颜色,则移到 OnGetCellStyle。

6

启用 cxGrid 功能

ShowGroupPanel、ShowFooter、GroupSummaries、ShowFilterRow、ShowFilterButtons、ShowFindPanel;汇总用 Columns[i].SummaryType,分带用 Bands 和 Columns[i].Band,布局用 SaveLayoutToFile。

7

激活

数据集打开后,在数据源上设置 Active := True。

哪些内容无法一一对应

规划迁移之前请先阅读这些内容。

MigrateFromDBGrid

一个包含 40 件产品、带 Category 查阅字段的 TClientDataSet,显示在两个页面上:“From TDBGrid”和“From cxGrid”。

位置

sgcUI 安装程序会把它放在 Demos\Grid\Delphi\MigrateFromDBGrid:MigrateFromDBGrid.dpr、frmMain.pas、frmMain.dfm 和一个 readme.html。

运行方法

在 Delphi 7 到 13 的任意版本中打开 MigrateFromDBGrid.dpr,构建 Win32 或 Win64 并运行。每个页面都会把 TDBGrid 或 cxGrid 的概念与对应的 sgcGrid 项并排列出。

自检

MigrateFromDBGrid.exe /test 会检查列和选项的映射、复制文本、分组、页脚汇总、分带、布局往返,以及在注册版中的写回和卡片视图,全部检查通过后以 0 退出。

公平地说:cxGrid 提供 sgcGrid 没有的东西,例如在一个网格控件中使用多个视图和层级,以及 INI 布局,而且它还附带一大套其他控件。如果您的应用依赖这些,迁移的工作量会比本页显示的更大。如果您使用的正是上面列出的网格功能,并希望以单个产品的形式、带完整源代码、在 Delphi 7 到 13 中使用,那么 sgcGrid 是合适的选择。完整功能列表请参阅 sgcGrid 产品页面。

超值之选:All-AccesseSeGeCe 全部产品,含高级支持,每年 €1,059 起。
查看 All-Access 价格

今天就迁移您的第一个网格

下载包含 sgcGrid 和 MigrateFromDBGrid 演示的 sgcUI 试用版,迁移您的第一个窗体。