Firemonkey use StylesData to set property of array object in style

2.1k views Asked by At

I try to set the property of an object when filling a ListBox with ListBoxItems. The object is an ellipse added to the style used by the ListBox. The line of code below raises an exception:

ListBoxItem.StylesData['ellipsestyle.fill.Gradient.Points.Points[0].Color'] := newAlphaColor;

As a workaround, I tried to reach the property by getting the ellipsestyle object with ListBoxItem.FindStyleRessource, but the function returns nil.

Thank you !

1

There are 1 answers

5
kami On

StylesData can`t provide access to 'complex' properties. you can do next workaround:

var
  Obj: TObject;
  myListBoxItem: TListBoxItem;
begin
  // create new item
  myListBoxItem:=TListBoxItem.Create(nil);
  ListBox1.AddObject(myListBoxItem);
  myListBoxItem.StyleLookup:='listboxitembottomdetail';

  myListBoxItem.StylesData['ellipsestyle.fill.Kind']:=TValue.From<TBrushKind>(TBrushKind.Gradient);

  // access to GradientPoints collection 
  Obj:=myListBoxItem.StylesData['ellipsestyle.fill.Gradient.Points'].AsObject;
  if not (Obj is TGradientPoints) then
    Exit;

  TGradientPoints(Obj).Points[0].Color:=TAlphaColorRec.Blanchedalmond;
  TGradientPoints(Obj).Points[1].Color:=TAlphaColorRec.Alpha;

About FindStyleResource:

First place, where you can get access to style object - OnApplyStyleLookup event of specified ListBoxItem. Before OnApplyStyleLookup (for example - immediatelly after creating Listboxitem) you cannot get access to style.

So, move your code to ListBoxItem.OnApplyStyleLookup and change it like this:

procedure TForm2.ListBoxItem1ApplyStyleLookup(Sender: TObject);
var
  FMXObj: TFmxObject;
  Ellipse: TEllipse;
begin
  if not (Sender is TFmxObject) then
    Exit;
  FMXObj:=TFMXObject(Sender).FindStyleResource('ellipsestyle');// get object by it`s "StyleName".
  if not (FMXObj is TEllipse) then
    Exit;

  Ellipse:=TEllipse(FMXObj);
  Ellipse.Fill.Kind:=TBrushKind.Gradient;
  Ellipse.Fill.Gradient.Points.Points[0].Color:=TAlphaColorRec.Blueviolet;
  Ellipse.Fill.Gradient.Points.Points[1].Color:=TAlphaColorRec.Greenyellow;
end;

Also, you can force load style (this is not recommended way - by default, style for object loaded at the time of first painting):

var
  FMXObj: TFmxObject;
  Ellipse: TEllipse;
  myListBoxItem: TListBoxItem;
begin
  myListBoxItem:=TListBoxItem.Create(nil);
  ListBox1.AddObject(myListBoxItem);
  myListBoxItem.StyleLookup:='listboxitembottomdetail';

  // force load style
  myListBoxItem.NeedStyleLookup;
  myListBoxItem.ApplyStyleLookup; // this method also call OnApplyStyleLookup event

  FMXObj:=myListBoxItem.FindStyleResource('ellipsestyle');
  if not (FMXObj is TEllipse) then
    Exit;

  Ellipse:=TEllipse(FMXObj);
  Ellipse.Fill.Kind:=TBrushKind.Gradient;
  Ellipse.Fill.Gradient.Points.Points[0].Color:=TAlphaColorRec.Blanchedalmond;
  Ellipse.Fill.Gradient.Points.Points[1].Color:=TAlphaColorRec.Alpha;