My DBGrid is connected to a Datasource / ClientDataset / Provider / ADOQuery
I sort the grid with this code, which seems to work well
procedure TDataModuleBase.SortClientDataSet(AscendingFields, DescendingFields: string);
var
I : integer;
IndexNames : TStringList;
begin
try
ClientDataSetEntity.DisableControls;
ClientDataSetEntity.IndexName := '';
if (AscendingFields <> '') or (DescendingFields <> '') then
begin
IndexNames := TStringList.Create;
ClientDataSetEntity.GetIndexNames(IndexNames);
for I := IndexNames.Count - 1 downto 0 do
begin
if IndexNames[I] = 'index0' then
begin
ClientDataSetEntity.DeleteIndex(IndexNames[I]);
end;
end;
ClientDataSetEntity.AddIndex(
'index0',
AscendingFields,
[ixCaseInsensitive],
DescendingFields,
'',
0
);
ClientDataSetEntity.IndexName := 'index0';
end;
ClientDataSetEntity.First;
finally
ClientDataSetEntity.EnableControls;
end;
end;
But, when I had some rows selected, then after sorting the selectedrows is wrong. Or it at least shows it wrong.
For example, the grid shows data sorted on ID in the first column (1, 2, 3... and so on)
Now I select the second and the 3th row, so row with ID 2 and 3 is selected
ID | Name | |
---|---|---|
1 | John | |
2 | Mary | this is colored blue because it is selected |
3 | Bill | this is colored blue because it is selected |
Now I sort on the name column, and the selection stays on the 2nd and 3th row in the grid, but that is not the row with ID 2 and 3 anymore
ID | Name | |
---|---|---|
3 | Bill | |
1 | John | this is colored blue because was selected before the sort |
2 | Mary | this is colored blue because was selected before the sort |
I want the rows with ID 2 ad 3 to stay the selected rows, not 1 and 2
Is there a way to keep the correct selectedrows after sorting ?
I mean, if after the sort the row with ID 2 is now for example the 7th row in the DBGrid, than the 7th row should now be colored as selected, not the 2nd anymore.
Does this makes sense ?
A first approximation could be using bookmarks.
In the end the list of rows selected in a Grid (SelectedRows
property) is nothing more than a TBookmarkList
.
It would be about saving the state of that list before changing the sorting with the SortClientDataSet
procedure and once done, reselecting the rows using the saved information.
For testing, i used the OnTitleClick
event. You can try something like this:
procedure TForm4.DBGrid1TitleClick(Column: TColumn);
var
sel:TList<TBookmark>;
bm:TBookMark;
begin
sel := TList<TBookmark>.Create;
ClientDataSetEntity.DisableControls;
try
// Get the list of selected rows
for var i := 0 to (DBGrid1.SelectedRows.Count - 1) do begin
bm := DBGrid1.SelectedRows[i];
sel.Add(bm);
end;
// Sort using the title click column (for testing)
SortClientDataSet(Column.Field.FieldName, '');
// Unselect All
DBGrid1.SelectedRows.Clear;
// selectwith the saved information
for var i := 0 to (sel.Count - 1) do begin
ClientDataSetEntity.GotoBookmark(sel[i]);
DBGrid1.SelectedRows.CurrentRowSelected := True;
end;
finally
ClientDataSetEntity.EnableControls;
FreeAndNil(sel);
end;
end;
This is the result. Looks fine.