I have a TStringGrid, and I want to delete the selected row. Basic things I've tried only delete the last row. How do I delete an arbitrary row?
2 Answers
If the code you've tried only deletes the last row, then you're probably just decrementing the RowCount
property. That indeed always makes its modifications on the end of the list of rows. With that in mind, you could write code to ensure that the row you no longer want is the one at the end, and then delete the last row. (The most direct way would be to move the row, and there's a MoveRow
method, but it's protected. If you wish to call protected methods, though, you may as well just call DeleteRow
instead.)
Using only public and published members, it's possible to write a loop that deletes an arbitrary row. For example, here's some code inspired by Scalabium Software's FAQ on this topic:
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;
It copies the contents of each row below the one you wish to delete into the row above. At the end of the loop, the row you wish to delete has been overwritten (by the row immediately below it) and there are two copies of the final row. Then it simply deletes the final row.
To delete the current row of the grid, call the function like this:
DeleteRow(Grid, Grid.Row);
The selected row of the grid is given by its Row
property.
TCustomGrid
has a DeleteRow
method, but it's protected, so you can't call it except from within descendants of that class. It's easy to circumvent that restriction, though. Declare a TCustomGrid
descendant, and then type-cast your grid control to that new type. Call DeleteRow
on the result.
type
TCustomGridAccess = class(TCustomGrid) end;
procedure DeleteGridRow(g: TCustomGrid; row: Integer);
begin
TCustomGridAccess(g).DeleteRow(row);
end;
This works because in Delphi, members with protected visibility are implicitly public within the same unit as the class's declaration. Although TCustomGrid
is declared in the Grids unit, our TCustomGridAccess
class is declared in your unit, so your unit has access to all its protected methods, including DeleteRow
.
If your Delphi version is new enough, then you can use a class helper. Class helpers can access protected members and don't require type-casting to technically unrelated types.
type
TCustomGridHelper = class helper for TCustomGrid
public
procedure DelRow(ARow: Integer);
end;
procedure TCustomGridHelper.DelRow(ARow: Integer);
begin
Self.DeleteRow(ARow);
end;
Then, simply use the unit where you've declared the helper. Any descendant of TCustomGrid
will automatically have a DelRow
method, which you can call just like any other grid method:
grid.DelRow(grid.Row);