Firemonkey Grid Control - выравнивание столбца справа

Я использую элемент управления FireMonkey Grid, но у меня есть постоянная проблема при попытке выровнять столбец вправо. Из сообщений других пользователей мне удалось создать новый тип TColumn, применить стиль к нему (текст как HorzAlign=taTrailing) и теоретически - подумал, что это будет решением. Значения предоставляются функцией OnGetValue для элемента управления Grid.

Проблема, однако, заключается в том, что, хотя вначале все выглядит хорошо, если вы прокручиваете колесо / колесо мыши и т. Д., Новый столбец типа TColumn не отображается для правильного обновления с использованием метода / кода ниже. Это может быть ошибка / особенность Grid (или как я это делаю). Я пробовал.ReAlign и т.д...; но безрезультатно. Единственный способ вернуть сетку в соответствие - это, например, изменить размер столбца - что тогда правильно перерисовывается?

Приведенный ниже код показывает, что это простой TGrid с 2 столбцами, 1 со стандартным StringColumn и 1 моим новым StringColNum (без выравнивания по правому краю). - Любая помощь, оцениваемая как эта, является основным требованием любой работы по сетке.

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.Objects, FMX.Grid,
  FMX.Layouts, FMX.Edit;

type
  TForm1 = class(TForm)
    Grid1: TGrid;
    Button1: TButton;
    StyleBook1: TStyleBook;
    procedure Grid1GetValue(Sender: TObject; const Col, Row: Integer;
      var Value: Variant);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  TStringColNum = class(TStringColumn)
  private
    function CreateCellControl: TStyledControl; override;
  public
    constructor Create(AOwner: TComponent); override;
  published
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

constructor TStringColNum.Create(AOwner: TComponent);
begin
  inherited;
end;

function TStringColNum.CreateCellControl: TStyledControl;
var
  t:TEdit;
begin
  Result:=TStringColNum.Create(Self);
  Result.StyleLookup := 'textrightalign';
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  Grid1.AddObject(TStringColumn.Create(Self));
  Grid1.AddObject(TStringColNum.Create(Self)); // Right Aligned column?

  Grid1.RowCount:=5000;
  Grid1.ShowScrollBars:=True;
end;

procedure TForm1.Grid1GetValue(Sender: TObject; const Col, Row: Integer;
  var Value: Variant);
var
  cell: TStyledControl;
  t: TText;
begin
  if Col=0 then
    Value:='Row '+IntToStr(Row);;

  if Col=1 then
    begin
      cell := Grid1.Columns[Col].CellControlByRow(Row);
      if Assigned(cell) then
        begin
          t := (Cell.FindStyleResource('text') as TText);
          if Assigned(t) then
            t.Text:='Row '+IntToStr(Row);
        end;
    end;
end;

end.

С уважением. Ян.

6 ответов

Решение

Все это напоминает мне, что я до сих пор не написал в своем блоге об этом.

В любом случае, ячейка сетки может быть любым потомком TStyledControl (практически любого элемента управления). По умолчанию для текстовой ячейки используется TTextCell, который является просто TEdit. Быть TEdit означает, что изменить выравнивание очень просто: просто измените свойство TextAlign. Не нужно возиться со стилями (если вы действительно не хотите).

Ваш столбец должен создать ваши ячейки в методе CreateCellControl. Вы фактически создаете экземпляр своей колонки, которая является вашей главной проблемой.

Вам не нужен метод Create для вашего столбца (он ничего не делает), поэтому удалите его (если он вам не нужен для чего-то другого) и измените ваш CreateCellControl.

function TStringColNum.CreateCellControl: TStyledControl;
begin
  Result:=inherited;
  TTextCell(Result).TextAlign := taTrailing;
end;

Наконец, ваш обработчик события GetValue не должен делать ничего, кроме как возвращать значение:

procedure TForm1.Grid1GetValue(Sender: TObject; const Col, Row: Integer;
  var Value: Variant);
begin
  if Col=0 then
    Value:='Row '+IntToStr(Row);

  if Col=1 then
    Value := 'Row '+IntToStr(Row);
end;

Я думаю, что это лень Embarcadero.

добавление / изменение 3 строк в FMX.Grid.pas решает эту проблему.

вместо модификации оригинального FMX.Grid pas, я рекомендую скопировать оригинальный FMX.Grid pas в ваш каталог Project, в том числе в вашем Project (добавить в Project) и добавить / изменить следующие строки.

TColumn = class(TStyledControl)
  private const
    HorzTextMargin = 2;
    VertTextMargin = 1;
  private
    FReadOnly: Boolean;
    FHorizontalAlign:TTextAlign;//Add this Line *********
    FEditMode: Integer;
    FApplyImmediately: boolean;
    ...
    ...
    procedure UpdateCell(ARow: Integer);
  published
    property HorizontalAlign: TTextAlign read FHorizontalAlign write FHorizontalAlign;//add this line *******
    property Align;
    property ClipChildren default False;

procedure TColumn.DefaultDrawCell(const Canvas: TCanvas; const Bounds: TRectF; const Row: Integer;
  const Value: TValue; const State: TGridDrawStates);
var
  R: TRectF;
  Layout: TTextLayout;
  LocalRow: Integer;
begin
  if FDrawable <> nil then
    FDrawable.DrawCell(Canvas, Bounds, Row, Value, State)
  else
...
...
      Layout.Opacity := AbsoluteOpacity;
      (*remark this line *****************
      Layout.HorizontalAlign := Grid.TextSettingsControl.ResultingTextSettings.HorzAlign;
      *)
      Layout.HorizontalAlign := HorizontalAlign;//add this line *****

наконец, вы можете установить новое свойство в вашем проекте. например:

MyColumn.HorizontalAlign: = TTextAlign.taCenter;

Другое решение:

Grid1.ApplyStyleLookup();
MyCol1.DefaultTextSettings.HorzAlign:=TTextAlign.taCenter;

Решение "Suat DMK" работает нормально, вы должны recompile Fmx.Bind.DBLinks.pas and Fmx.Bind.Editors.pas если вы собираетесь использовать ссылки на БД.

После этого вы просто помещаете событие OnPainting:

SGrid1.ColumnByIndex(1).HorizontalAlign := TTextAlign.Leading;

Нисходящие столбцы не очень хорошо работают с живыми привязками, так как администратор привязок создает столбцы, поэтому вам придется возиться с этим по убыванию. Ни элегантный, ни практичный, на мой взгляд.

Просто выровняйте ваши ячейки в событии OnPainting сетки.

I := Col;
for J := 0 to Grid1.RowCount - 1 do
begin
  T := TTextCell(Grid1.Columns[I].Children[J]);
  T.TextAlign := TTextAlign.taTrailing;
end;

Если вы используете livebindings, когда у вас меньше шансов настроить создаваемый класс столбца, но вы можете создать помощников для Column, который устанавливает некоторые атрибуты отдельных элементов управления ячейки. Не слишком элегантно, но просто и работает:

unit GridColumnHelper;

interface

uses
  Fmx.Types, Fmx.Controls, Fmx.Grid, Fmx.Edit;

type
  TGridColumnHelper = class helper for TColumn
  public
    procedure SetEditMaxLength(aValue: Integer);
    procedure SetEditTextAlign(aValue: TTextAlign);
  end;

implementation

{ TGridColumnHelper }

procedure TGridColumnHelper.SetEditMaxLength(aValue: Integer);
var
  lControl: TStyledControl;
begin
  for lControl in FCellControls do
  begin
    if lControl is TEdit then
      (lControl as TEdit).MaxLength := aValue;
  end;
end;

procedure TGridColumnHelper.SetEditTextAlign(aValue: TTextAlign);
var
  lControl: TStyledControl;
begin
  for lControl in FCellControls do
  begin
    if lControl is TEdit then
      (lControl as TEdit).TextAlign := aValue;
  end;
end;

end.

После того, как привязка заполнит сетку, вы можете вызвать помощников:

MyGrid.Columns[0].SetEditTextAlign(TTextAlign.taTrailing);
MyGrid.Columns[1].SetEditMaxLength(15);
Другие вопросы по тегам