Search code examples
delphifiremonkeytstringgrid

FMX Custom Header for TStringGrid


I am using this code to set the column Headers for my TStringGrid (FMX - 10.4.1)

procedure TForm1.StringGrid1ApplyStyleLookup(Sender: TObject);
var
  Header: THeader;
  HeaderItem: THeaderItem;
  I: Integer;
begin
  Header:= THeader((Sender as TStringGrid).FindStyleResource('header'));
  if Assigned(Header) then
    begin
      for I := 0 to pred(Header.Count) do
        begin
          HeaderItem:= Header.Items[I];
          HeaderItem.StyledSettings := HeaderItem.StyledSettings - [TStyledSetting.Size, TStyledSetting.FontColor];
          HeaderItem.Font.Size := 20;
          HeaderItem.FontColor:= TAlphaColors.Blue;
          HeaderItem.TextSettings.HorzAlign := TTextAlign.Center;
          HeaderItem.TextSettings.VertAlign := TTextAlign.Center;
      end;
      Header.Height := 28;
  end;
end;

I get this result as expected

enter image description here

However, if I'm updating the list with some new data, the header is back to default style

enter image description here

Why is it different now? Why ApplyStyleLookup is applied only once ?

How can I make sure the correct settings will be applied to my headers each and every time ? Thanks

Here below a sample code

object Form1: TForm1
  Left = 0
  Top = 0
  Caption = 'Form1'
  ClientHeight = 400
  ClientWidth = 600
  Position = DesktopCenter
  FormFactor.Width = 320
  FormFactor.Height = 480
  FormFactor.Devices = [Desktop]
  DesignerMasterStyle = 0
  object StringGrid1: TStringGrid
    Align = Client
    CanFocus = True
    ClipChildren = True
    Margins.Left = 5.000000000000000000
    Margins.Top = 50.000000000000000000
    Margins.Right = 5.000000000000000000
    Margins.Bottom = 5.000000000000000000
    Size.Width = 590.000000000000000000
    Size.Height = 345.000000000000000000
    Size.PlatformDefault = False
    StyleLookup = 'gridstyle'
    TabOrder = 0
    RowCount = 0
    Options = [ColumnResize, ColLines, RowLines, RowSelect, Tabs, Header]
    OnApplyStyleLookup = StringGrid1ApplyStyleLookup
    Viewport.Width = 586.000000000000000000
    Viewport.Height = 320.000000000000000000
    object StringColumn1: TStringColumn
      Header = 'Test'
    end
  end
  object Button1: TButton
    Position.X = 8.000000000000000000
    Position.Y = 8.000000000000000000
    Size.Width = 177.000000000000000000
    Size.Height = 33.000000000000000000
    Size.PlatformDefault = False
    TabOrder = 1
    Text = 'Show Form Properties'
    OnClick = Button1Click
  end
  object Text1: TText
    Anchors = [akLeft, akTop, akRight]
    Position.X = 192.000000000000000000
    Position.Y = 8.000000000000000000
    Size.Width = 401.000000000000000000
    Size.Height = 33.000000000000000000
    Size.PlatformDefault = False
    Text = 'Unkown'
    TextSettings.HorzAlign = Trailing
  end
end


unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  System.Rtti, System.TypInfo,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs, FMX.Grid.Style,
  FMX.StdCtrls, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Grid, FMX.Header,
  FMX.Objects;

type
  TForm1 = class(TForm)
    StringGrid1: TStringGrid;
    Button1: TButton;
    Text1: TText;
    StringColumn1: TStringColumn;
    procedure Button1Click(Sender: TObject);
    procedure StringGrid1ApplyStyleLookup(Sender: TObject);
  private
    { Private declarations }
    FCount: cardinal;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation


{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
var
  PropList: PPropList;
  PropCount, PropIndex: Integer;
begin
  StringGrid1.ClearColumns;

  PropCount:= GetPropList(Form1, PropList);
  StringGrid1.RowCount:= PropCount;
  StringGrid1.RowHeight:= 20;

  StringGrid1.AddObject(TStringColumn.Create(StringGrid1));
  StringGrid1.Columns[0].Width:= (StringGrid1.Width - 24) / 2;
  StringGrid1.Columns[0].HorzAlign:= TTextAlign.Leading;
  StringGrid1.Columns[0].Header:= 'Property';

  StringGrid1.AddObject(TStringColumn.Create(StringGrid1));
  StringGrid1.Columns[1].Width:= (StringGrid1.Width - 24) / 2;
  StringGrid1.Columns[1].HorzAlign:= TTextAlign.Leading;
  StringGrid1.Columns[1].Header:= 'Value';

  for PropIndex:= 0 to pred(PropCount) do
    begin
      StringGrid1.Cells[0, PropIndex]:= PropList[PropIndex].Name;
      StringGrid1.Cells[1, PropIndex]:= GetPropValue(Form1, PropList[PropIndex].Name, true);
  end;
end;

procedure TForm1.StringGrid1ApplyStyleLookup(Sender: TObject);
var
  Header: THeader;
  HeaderItem: THeaderItem;
  I: Integer;
begin
  inc(FCount);
  Text1.Text:= Format('Executed [%.3d]', [FCount]);

  Header:= THeader((Sender as TStringGrid).FindStyleResource('header'));
  if Assigned(Header) then
    begin
      for I := 0 to pred(Header.Count) do
        begin
          HeaderItem:= Header.Items[I];
          HeaderItem.StyledSettings := HeaderItem.StyledSettings - [TStyledSetting.Size, TStyledSetting.FontColor];
          HeaderItem.Font.Size := 20;
          HeaderItem.FontColor:= TAlphaColors.Blue;
          HeaderItem.TextSettings.HorzAlign := TTextAlign.Center;
          HeaderItem.TextSettings.VertAlign := TTextAlign.Center;
      end;
      Header.Height := 28;
  end;
end;

end.

Solution

  • I can not answer "why" questions, otherwise than "by design".

    But to solve your problem, call

    StringGrid1.NeedStyleLookup;
    

    after you have made your changes to the structure (number of columns / rows) of the grid.