我编写了一个类似 TListBox
的控件(类似于 Doctor Bob's SpeedBox )。
它运行良好,但有一个问题除外:分配给属性 Items
的字符串在启动时不会加载到 TListBox
字段中。我发现,我的过程 SetItem
在创建时没有被调用,因为组件读取器使用 TStrings.Add
分配字符串。
该控件的源代码:
unit HKS.Controls.FilterListBox;
interface
uses
System.Classes, Vcl.Controls, Vcl.StdCtrls;
type
THKSFilterListBox = class(TWinControl)
strict private
FEdit: TEdit;
FItems: TStrings;
FListBox: TListBox;
procedure SetItems(const Value: TStrings);
procedure ReInitListBoxItems;
public
constructor Create(AOwner: TComponent); override;
destructor Destroy; override;
procedure SetBounds(ALeft, ATop, AWidth, AHeight: Integer); override;
published
property Items: TStrings read FItems write SetItems;
end;
procedure Register;
implementation
uses
System.SysUtils, Vcl.Graphics, Winapi.Windows;
procedure Register;
begin
RegisterComponents('HKS', [THKSFilterListBox]);
end;
{ THKSFilterListBox }
constructor THKSFilterListBox.Create(AOwner: TComponent);
begin
inherited;
FItems := TStringList.Create;
FEdit := TEdit.Create(Self);
FEdit.Parent := Self;
FListBox := TListBox.Create(Self);
FListBox.Parent := Self;
ReInitListBoxItems; // has no effect since data is not loaded yet
end;
destructor THKSFilterListBox.Destroy;
begin
FreeAndNil(FListBox);
FreeAndNil(FEdit);
FreeAndNil(FItems);
inherited;
end;
procedure THKSFilterListBox.ReInitListBoxItems;
var
LFilterText: String;
begin
LFilterText := AnsiUpperCase(Trim(FEdit.Text));
FListBox.Items.BeginUpdate;
try
if LFilterText <> '' then
begin
// some filter routine
end else
FListBox.Items.Assign(FItems);
finally
FListBox.Items.EndUpdate;
end;
end;
procedure THKSFilterListBox.SetBounds(ALeft, ATop, AWidth, AHeight: Integer);
const
cEditHeightAddon = 12;
cMargin = 2;
var
LListBoxTop: Integer;
begin
inherited;
FEdit.SetBounds(0, 0, Self.Width, Abs(Font.Height) + cEditHeightAddon);
LListBoxTop := FEdit.BoundsRect.Bottom + cMargin;
FListBox.SetBounds(0, LListBoxTop, Self.Width, Self.Height - LListBoxTop);
end;
// is not called on startup because items are added one by one with "TStrings.Add"
procedure THKSFilterListBox.SetItems(const Value: TStrings);
begin
FItems.Assign(Value);
ReInitListBoxItems;
end;
end.
我需要自己的 Items
实例,因为并非所有项目都会显示,具体取决于 FEdit.Text
中的过滤字符串。
从 dfm 加载属性后有什么方法可以调用 ReInitListBoxItems
吗?
最佳答案
Is there any way to call ReInitListBoxItems after properties have been loaded from dfm?
覆盖组件的Loaded
方法。
Initializes the component after the form file has been read into memory.
Do not call the protected Loaded method. The streaming system calls this method after it loads the component's form from a stream.
When the streaming system loads a form or data module from its form file, it first constructs the form component by calling its constructor, then reads its property values from the form file. After reading all the property values for all the components, the streaming system calls the Loaded methods of each component in the order the components were created. This gives the components a chance to initialize any data that depends on the values of other components or other parts of itself.
type
THKSFilterListBox = class(TWinControl)
...
protected
procedure Loaded; override;
...
end;
procedure THKSFilterListBox.Loaded;
begin
inherited;
ReInitListBoxItems;
end;
关于delphi - 未加载自定义控件的已发布 TStrings 属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32589679/