已发布的TStrings-property未加载以进行自定义控件

时间:2015-09-15 15:15:07

标签: delphi custom-controls deserialization

我写了一个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

1 个答案:

答案 0 :(得分:2)

  

在从dfm加载属性后,有没有办法调用ReInitListBoxItems?

覆盖组件的Loaded方法。

  

在读取表单文件后初始化组件   存储器中。

     

不要调用受保护的Loaded方法。流媒体系统调用   从流加载组件的表单后,此方法。

     

当流媒体系统从表单加载表单或数据模块时   它首先通过调用它来构造表单组件   然后,构造函数从表单文件中读取其属性值。后   读取所有组件的所有属性值,即流   系统按顺序调用每个组件的Loaded方法   组件已创建。这为组件提供了机会   初始化任何依赖于其他组件或的值的数据   本身的其他部分。

type
  THKSFilterListBox = class(TWinControl)
    ...
  protected
    procedure Loaded; override;
    ...
  end;

procedure THKSFilterListBox.Loaded;
begin
  inherited;
  ReInitListBoxItems;
end;