如何删除TStringGrid中的一行?

16

我有一个TStringGrid,想要删除选定的行。我尝试了一些基本操作,但只能删除最后一行。如何删除任意一行?

3个回答

17
如果你尝试的代码只删除了最后一行,那么你可能只是在减少 RowCount 属性的值。这确实总是对行列表的末尾进行修改。考虑到这点,你可以编写代码来确保你不再需要的那一行位于末尾,然后再删除最后一行。(最直接的方法是移动该行,有一个 MoveRow 方法,但它是受保护的。如果你想调用受保护的方法,你可以干脆调用DeleteRow。)
使用仅公共成员和发布的成员,可以编写一个循环程序来删除任意行。例如,以下代码受Scalabium Software关于此主题的常见问题解答启发:
procedure DeleteRow(Grid: TStringGrid; ARow: Integer);
var
  i: Integer;
begin
  for i := ARow to Grid.RowCount - 2 do
    Grid.Rows[i].Assign(Grid.Rows[i + 1]);
  Grid.RowCount := Grid.RowCount - 1;
end;

它将每一行下面的内容复制到上一行中,以删除目标行。循环结束时,你要删除的那一行已经被下方行覆盖,并且最后一行有两份副本。然后函数会简单地删除最后一行。

要删除表格的当前行,请按以下方式调用该函数:

DeleteRow(Grid, Grid.Row);

另外,如果您只需要对象(例如我自己,动态地从对象中的单元格绘制数据而不是单元格内容),那么请使用Grid.Objects[0, I + 1]替换第二行。这比替换未被使用的整个内容要快一些。 - Jerry Dodge

10

网格的选定行由其 Row 属性给出。

TCustomGrid 有一个 DeleteRow 方法,但它是受保护的,因此除了该类的后代之外,您无法调用它。然而,绕过这个限制很容易。声明一个 TCustomGrid 的后代,然后将您的网格控件强制转换为该新类型。在结果上调用 DeleteRow

type
  TCustomGridAccess = class(TCustomGrid) end;

procedure DeleteGridRow(g: TCustomGrid; row: Integer);
begin
  TCustomGridAccess(g).DeleteRow(row);
end;
这是因为在Delphi中,具有protected可见性的成员在与类声明相同的单元内被隐式视为public。尽管TCustomGrid在Grids单元中声明,但我们的TCustomGridAccess类在your单元中声明,因此您的单元可以访问它的所有受保护方法,包括DeleteRow。
如果您的Delphi版本足够新,则可以使用类助手。类助手可以访问受保护的成员,无需将类型强制转换为技术上不相关的类型。
type
  TCustomGridHelper = class helper for TCustomGrid
  public
    procedure DelRow(ARow: Integer);
  end;

procedure TCustomGridHelper.DelRow(ARow: Integer);
begin
  Self.DeleteRow(ARow);
end;

接下来,只需使用已声明帮助程序的单元。任何TCustomGrid的后代都将自动拥有DelRow方法,您可以像调用其他网格方法一样调用它:

grid.DelRow(grid.Row);

不错的解决方案。不幸的是,我在FireMonkey TCustomGrid (FMX.Grid)中找不到DeleteRow。我是对的吗?还是我错过了什么? - ArieKanarie

0

我找到了一个Firemonkey的解决方案,因为我没有找到ROWS功能:

procedure TMainForm.StringGridDeleteRow(Grid: TStringGrid;
  ARow: integer);
var
  i, j: Integer;
begin
  for i := ARow to Grid.RowCount - 2 do
    for j := 0 to Grid.ColumnCount-1 do
        Grid.Cells[j,i] := Grid.Cells[j, i+1];
  Grid.RowCount := Grid.RowCount - 1;
end;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接