我不确定是否有可能 - 但它似乎应该对我而言。基本上,我想在更改StyleLookup时触发所有组件来刷新它们的样式。
我有一个名为BaseStyleLabel
的TLabel FMXComponent。组件的StyleName
属性是'BaseStyle'。它本身从样式资源中查找其样式,因此其StyleLookup
属性设置为'BaseStyle1'。我还有'BaseStyle2','BaseStyle3' ......
我有一个名为MyTextLabel
的依赖Tlabel,其StyleLookup
属性设置为BaseStyle
,即BaseStyleLabel
的StyleName。
一切似乎都很好。我看到MyTextLabel
继承了'BaseStyle1'的MyBaseStyle
样式。
当我执行这行代码时
BaseStyleLabel.StyleLookup := 'BaseStyle2';
Self.repaint; // repaint whole form
我希望BaseStyleLabel
更改为'BaseStyle2'(它确实如此)。但是,MyTextLabel
也应该更改样式,然后看起来像'BaseStyle2',但它不会:它仍然是 BaseStyle1
;
限定符是BaseLabel和MyTextLabel都来自样式资源。它们实际上不是在表单上创建的组件,它们是由样式创建的。
所以我的问题是这个。
...编辑....下面是请求的示例...
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.
使用以下样式文件
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
答案 0 :(得分:0)
好的 - 我全力以赴可以提出解决方案。
我浏览了TStyledControl
的祖先课程。没有全局触发器可以使样式查找级联。单个组件刷新其样式的事实不会导致任何组件(恰好依赖于组件StyleName)进行刷新。因此,您似乎必须手动找到所有受影响的组件并将其全部更新。
这对我来说不够好,所以我为TStyledControl写了一个帮助方法。
unit FMX.CascadingStyleLookup;
// Written by Glen Kleidon - 2018 - twitter: @sobaldrick4
interface
uses System.SysUtils, FMX.Types, FMX.Forms, FMX.Controls;
Type
TCascadingStyleLookup = Class Helper for TStyledControl
Procedure CascadeStyleLookup(AStyleLookup: String); overload;
procedure CascadeStyleLookup(AStyleLookup: string;
AComponent: TFMXObject); overload;
Function FindUltimateParentForm(AChild: TFMXObject): TFMXObject;
End;
implementation
procedure TCascadingStyleLookup.CascadeStyleLookup(AStyleLookup: String);
var
lUltimateParent: TFMXObject;
begin
// Apply New style to myself.
Self.styleLookup := AStyleLookup;
// Check if I have dependent Styles.
if (length(Self.StyleName) = 0) then
exit;
// Re-Apply my own style to everything.
lUltimateParent := Self.FindUltimateParentForm(Self);
if lUltimateParent <> nil then
CascadeStyleLookup(Self.StyleName, lUltimateParent);
end;
procedure TCascadingStyleLookup.CascadeStyleLookup(AStyleLookup: string;
AComponent: TFMXObject);
var
lChild: TFMXObject;
lStyledControl: TStyledControl;
begin
if (AComponent = nil) or (AComponent.Children = nil) then
exit;
if (AComponent.InheritsFrom(TStyledControl)) then
begin
lStyledControl := AComponent as TStyledControl;
if SameText(AStyleLookup, lStyledControl.styleLookup) then
begin
// re-apply
lStyledControl.styleLookup := AStyleLookup;
// Re-cascade this style.
if (length(lStyledControl.StyleName) > 0) and
(NOT(SameText(lStyledControl.styleLookup, AStyleLookup))) then
CascadeStyleLookup(lStyledControl.StyleName);
end;
end;
if AComponent.Children = nil then
exit;
// Check the children of this component for the style.
for lChild in AComponent.Children do
CascadeStyleLookup(AStyleLookup, lChild);
end;
function TCascadingStyleLookup.FindUltimateParentForm(AChild: TFMXObject)
: TFMXObject;
begin
Result := nil;
if (AChild.Parent <> nil) and (NOT(AChild.Parent.InheritsFrom(TForm))) then
Result := FindUltimateParentForm(AChild)
else
Result := AChild.Parent;
end;
end.
这允许为组件所在的整个表单自动搜索和更新任何嵌套的“stylelookup”属性。
我使用附加组件MyTextLabel2
更新了原始示例,该组件取决于MyTextLabel
的样式。
因此,现在将BaseStyleLabel
设置为任何* BaseStyle1,2 或 3 *将级联到MyTextLabel。当MyTextLabel更改其样式时,它将级联到MyTextLabel2。因此,只需调用BaseStyleLabel.CascadeStyleLookup('BaseStyle2')
即可更新BaseStyleLabel时,所有三个标签都会显示“STYLE TWO”;
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,
FMX.CascadingStyleLookup
;
type
TForm1 = class(TForm)
MyTextLabel: TLabel;
StyleBook1: TStyleBook;
BaseStyleLabel: TLabel;
Button1: TButton;
MyTextLabel2: TLabel;
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.StyleName := 'MyTextBaseStyle';
MyTextLabel.StyleLookup := 'BaseStyle'; // also says "STYLE ONE"
// New component MyTextLabel2 points to whatever "MyTextLabel" is styled as...
MyTextLabel2.StyleLookup := 'MyTextBaseStyle'; // also says "STYLE ONE",
// (from MyTextLabel)
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
// Change BaseStyle Label to "STYLE TWO" (now cascades to all)
BaseStyleLabel.CascadeStyleLookup('BaseStyle2');
end;