sortingdelphitclientdatasetdelphi-12-athens

how to restore the selectedrows after sorting in dbgrid and clientdataset


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 ?


Solution

  • 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.

    enter image description here