FMX TGrid OnGetValue после перемещения столбца

У меня есть Grid с включенными столбцами перемещения и код:

type
  TRec = record
    Col0,
    Col1,
    Col2: string;
  end;

var
  Data: TArray<TRec>;

procedure TFormMain.GridGetValue(Sender: TObject; const Col, Row: Integer; var Value: TValue);
begin
  case Col of
    0:  Value := Data[Row].Col0;
    1:  Value := Data[Row].Col1;
    2:  Value := Data[Row].Col2;
  end;
end;

При перемещении столбца этот код OnGetValue работает некорректно (отображаются данные столбцов на предыдущих позициях). Как это исправить? Должен ли я использовать событие OnColumnMoved и запомнить положение новых столбцов вручную?

1 ответ

Решение

Хорошо, это мой собственный ответ:

Мы должны добавить вспомогательную функцию в наш TRec для чтения полей по индексу:

type
  TRec = record
    Col0,
    Col1,
    Col2: string;
    function GetField(AIndex: Integer): string;
  end;

function TRec.GetField(AIndex: Integer): string;
begin
  case AIndex of
    0:  Result := Col0;
    1:  Result := Col1;
    2:  Result := Col2;
  else
    Result := '';
  end;
end;

Также 2 функции для сохранения и восстановления столбцов TGrid с использованием файла Ini:

type
  TColumnData = record
    Pos:     UInt8;
    Visible: Boolean;  
    Width:   UInt16;
  end;

procedure LoadColumns(AGrid: TGrid; const ASection, AIdent: string);
var
  I, J, ColsSize: Integer;
  A: TArray<TColumnData>;
  Col: TColumn;
begin
  for I := 0 to AGrid.ColumnCount - 1 do
    AGrid.Columns[I].Tag := I;
  SetLength(A, AGrid.ColumnCount);
  ColsSize := AGrid.ColumnCount*SizeOf(TColumnData);
  if ReadIni(<FileName>, ASection, AIdent, (@A[0])^, ColsSize) = ColsSize then
    for J := 0 to AGrid.ColumnCount - 1 do begin
      for I := 0 to AGrid.ColumnCount - 1 do begin
        Col := AGrid.Columns[I];
        if Col.Tag = A[J].Pos then begin
          Col.Index   := J;
          Col.Visible := A[J].Visible;
          Col.Width   := A[J].Width;
        end;
      end;
    end;
end;

procedure SaveColumns(AGrid: TGrid; const ASection, AIdent: string);
var
  I, ColsSize: Integer;
  A: TArray<TColumnData>;
  Col: TColumn;
begin
  SetLength(A, AGrid.ColumnCount);
  ColsSize := AGrid.ColumnCount*SizeOf(TColumnData);
  for I := 0 to AGrid.ColumnCount - 1 do begin
    Col := AGrid.Columns[I];
    A[I].Pos     := Col.Tag;
    A[I].Visible := Col.Visible;
    A[I].Width   := Round(Col.Width);
  end;
  WriteIni(<FileName>, ASection, AIdent, (@A[0])^, ColsSize);
end;

Теперь мы должны вызвать LoadColumns (которая также инициализирует поля Tag для столбцов) из OnFormCreate и SaveColumns из OnFormDestroy. И, наконец, код OnGetValue:

var
  Data: TArray<TRec>;

procedure TFormMain.GridGetValue(Sender: TObject; const Col, Row: Integer; var Value: TValue);
begin
  Value := Data[Row].GetField((Sender as TGrid).Columns[Col].Tag);
end;
Другие вопросы по тегам