delphi - 未加载自定义控件的已发布 TStrings 属性

标签 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 吗?

最佳答案

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/

相关文章:

Android - Seekbar 自定义进度缩放

c# - Visual Studio 2008 IDE 无法正确呈现自定义控件

post - Jackson 提供者未将 POST 数据反序列化为 Pojo (Jersey 2.0)

java - Spring Jackson 通过 Id 引用现有对象反序列化对象

delphi - 限制 Outlook 不返回任何内容的方法

performance - CharInSet 比 IN 慢很多,我应该修复 W1050 警告提示吗?

c# - 如何在WPF中正确刷新自定义形状?

java - 使用 Jackson 反序列化时防止 float 到 int 的转换

delphi - 在delphi中取消选择 TreeView 的元素

delphi - 优雅地放松 "Local procedure/function assigned to procedure variable"限制