在组件 属性 更改后更新 VirtualStringTree header

Update VirtualStringTree header after a component property has changed

我想创建一个名为 TMyComp 的组件。 该组件具有以下相关属性: property VirtualStringTree: TVirtualStringTreeproperty Columns: TMyCompColumns 作为 collection 项。

我的组件中的列与关联的 VirtualStringTree 中的 header 列相同。

我想做的是在标题更新时在 design-time 处重绘来自 VirtualStringTree 的 header 文本。

我的问题是我不知道如何触发 procedure RedrawVirtualStringTreeHeader,因为 class TMyCompColumns 甚至 TMyCompColumnsItem 都不知道它。

TMyCompColumnsItem = class(TCollectionItem)
  private
    FCaption: String;
    function GetPosition: Integer;
  protected
    function GetDisplayName: String; override;
    procedure SetIndex(Value: Integer);
  public
    constructor Create(Collection: TCollection); override;
    procedure Assign(Source: TPersistent); override;
  published
    property Caption: String read FCaption write FCaption;
  end;

  TMyCompColumns= class(TCollection)
  private
    FOwner: TComponent;
  protected
    function GetOwner: TPersistent; override;
    function GetItem(Index: Integer): TMyCompColumnsItem;
    procedure SetItem(Index: Integer; Value: TMyCompColumnsItem);
    procedure Update(Item: TMyCompColumnsItem);
  public
    constructor Create(AOwner: TComponent);
    function Add: TMyCompColumnsItem;
    property Items[Index: Integer]: TMyCompColumnsItem read GetItem write SetItem;
  end;

  TMyComp = class(TComponent)
  private
    FColumns: TMyCompColumns;
    FVirtualStringTree: TVirtualStringTree;
    procedure SetMyCompColumns(const Value: TMyCompColumns);
  protected
    { Protected declarations }
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  published
    property Columns: TMyCompColumns read FColumns write SetMyCompColumns;
    property VirtualStringTree: TVirtualStringTree read FVirtualStringTree write  FVirtualStringTree;
  end;

...

function TMyCompColumnsItem.GetDisplayName: String;
begin
  Result:= FCaption;
  RedrawVirtualStringTreeHeader; //<--- procedure not recognized!!!
end;

...

procedure TMyCompColumns.Update(Item: TMyCompColumnsItem);
begin
  inherited;
  //RedrawVirtualStringTreeHeader; ???or here
end;

procedure TMyComp.RedrawVirtualStringTreeHeader;
var
  i: Integer;
begin
  if Assigned(FVirtualStringTree) then
    begin
      FVirtualStringTree.Header.Options:= FVirtualStringTree.Header.Options + [hoVisible];
      FVirtualStringTree.Header.Columns.Clear;

      if FColumns.Count > 0 then
        for i := 0 to FColumns.Count-1 do
          with FVirtualStringTree.Header.Columns.Add do
            begin
              Text:= FColumns.Items[i].Caption;
              //...
            end;    
    end;
end;

经过一番搜索,这是答案:

  1. RedrawVirtualStringTreeHeader的触发已经通过TMyCompColumns里面的FOwner完成class.

procedure TMyCompColumns.Update(Item: TCollectionItem); begin inherited; (FOwner as TMyComp).RedrawVirtualStringTreeHeader; end;

  1. 我用 write SetCaption 更新了 property Caption: String read FCaption write FCaption 并添加了程序

procedure TMyCompColumnsItem.SetCaption(const Value: String); begin FCaption:= Value; Changed(False); //---> this will trigger TMyCompColumns.Update end;

事实上,秘密是 Changed(False); 触发了 Update

也感谢 TVirtualStringTree 组件的开源。