I am not sure if is possible - but it seems like it should be to me. Essentially, I want to trigger all the components to refresh their styles when I change a StyleLookup.
I have a FMXComponent which is a TLabel called BaseStyleLabel
. The StyleName
property of the component is 'BaseStyle'. It itself looks up its style from a style resource, so its StyleLookup
property is set to 'BaseStyle1'. I also have 'BaseStyle2', 'BaseStyle3' ...
I have a dependent Tlabel which is called MyTextLabel
and its StyleLookup
property is set to BaseStyle
, ie the StyleName of BaseStyleLabel
.
That all seems to work fine. I see that MyTextLabel
inherits the style from MyBaseStyle
of 'BaseStyle1'.
When I execute this line of code
BaseStyleLabel.StyleLookup := 'BaseStyle2';
Self.repaint; // repaint whole form
I expect that BaseStyleLabel
changes to 'BaseStyle2' (which it does). However, MyTextLabel
should also change style and then look like 'BaseStyle2', but it does not: it remains as BaseStyle1
;
The qualifier is that both BaseLabel and MyTextLabel are also from a style resource. They are not actually a component created on the form, they are created by the style.
So my question is this.
- Is this approach valid?
- Is there a standard approach eg using a Style Object which I can update?
- Have I just not refreshed the right thing or;
- used the wrong a method to refresh, maybe ApplyStyle?
...EDIT.... Below is the requested Example...
unit Unit1;
interface
uses
System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
FMX.Types, FMX.Graphics, FMX.Controls, FMX.Forms, FMX.Dialogs, FMX.StdCtrls;
type
TForm1 = class(TForm)
MyTextLabel: TLabel;
StyleBook1: TStyleBook;
BaseStyleLabel: TLabel;
Button1: TButton;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.fmx}
procedure TForm1.FormCreate(Sender: TObject);
begin
// Set up BaseStyleLabel as a Style Source
BaseStyleLabel.StyleName := 'BaseStyle';
// Set its Style to a Resources Style "STYLE ONE"
BaseStyleLabel.StyleLookup := 'BaseStyle1';
// Point MyTextLabel to whatever "BaseStyleLabel" is styled as...
MyTextLabel.StyleLookup := 'BaseStyle'; // also says "STYLE ONE"
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
//Change BaseStyle Label to "STYLE TWO" (works OK)
BaseStyleLabel.StyleLookup := 'BaseStyle2';
// ... BUT MyTextLabel stays as "STYLE ONE"
// can I repaint???
// Auto Cascade?
// What about when Other TLabels are part of a different component style?
end;
end.
Use the following Style File
object TStyleContainer
object TLabel
StyleName = 'BaseStyle1'
DesignVisible = False
Height = 17.000000000000000000
Position.X = 521.000000000000000000
Position.Y = 432.000000000000000000
Text = 'STYLE ONE'
Width = 120.000000000000000000
end
object TLabel
StyleName = 'BaseStyle2'
DesignVisible = False
Height = 17.000000000000000000
Position.X = 521.000000000000000000
Position.Y = 432.000000000000000000
Text = 'STYLE TWO'
Width = 120.000000000000000000
end
object TLabel
StyleName = 'BaseStyle3'
Height = 17.000000000000000000
Position.X = 521.000000000000000000
Position.Y = 432.000000000000000000
Text = 'STYLE 3'
Width = 120.000000000000000000
end
end
OK - I worked this all through can came up with a solution.
I looked through the ancestor class for
TStyledControl
. There is no global trigger to cause a style lookup to cascade. The fact that an individual component refreshes its style does not cause any components (which just so happen to depend on that components StyleName) to refresh. So it seems you have to locate all the affected components manually and update them all.This wasn't good enough for me, so I wrote a helper method for TStyledControl.
This allows any nested "stylelookup" properties to be automatically searched for and updated for the entire form where the component resides.
I updated my original example with an additional component
MyTextLabel2
which depends on the style ofMyTextLabel
.So, now setting
BaseStyleLabel
to any of *BaseStyle1, 2 or 3* will cascade to MyTextLabel. When MyTextLabel changes its style,this will cascade to MyTextLabel2. So, all three labels will show "STYLE TWO" when BaseStyleLabel is updated by simply callingBaseStyleLabel.CascadeStyleLookup('BaseStyle2')
;