【问题标题】:How to attach an object of any type with a TControl?如何使用 TControl 附加任何类型的对象?
【发布时间】:2013-11-22 18:13:00
【问题描述】:

我想添加一个带有 TTreeViewItem 的 TList 和一个带有另一个自定义类 (TRoom) 的对象。在delphi 2007中,有一个指针类型的“数据”字段已被替换为此处的TValue,我不知道如何使用。我已经在互联网上搜索了一些说它暂时无法处理自定义类型。

除了制作一个 hack 类之外,有人可以设计一种方法来实现这一点吗?

例如,下面的表单代码应该可以正常运行:-

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Rtti, System.Classes,
  System.Variants, FMX.Types, FMX.Controls, FMX.Forms, FMX.Dialogs,
  FMX.TreeView, FMX.Layouts, FMX.Edit;

type
  TRoom = class

    ID : WORD;
    Name : String;

  end;

  TForm1 = class(TForm)
    TreeView1: TTreeView;
    TreeViewItem1: TTreeViewItem;
    Button1: TButton;
    Edit1: TEdit;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
var
  List : TList;
begin

  // Get The List From TreeViewItem1
  // pani's Solution  - List := TList ( TreeViewItem1.TagObject );

  Edit1.Text := TRoom ( List.First ).Name;

end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Room : TRoom;
  List : TList;

begin

  List := TList.Create;
  Room := TRoom.Create;
  Room.ID := 5;
  Room.Name := IntToStr ( 5 );
  List.Add ( Room );

  // Add The List To TreeViewItem1    
  // pani's Solution  - TreeViewItem1.TagObject := List;

end;

end.

【问题讨论】:

  • TValue 是变体类型,使用Data.AsObject
  • 不起作用,编译器错误“不兼容的类型...”没有类型转换和“无效类型转换”。
  • @JerryDodge 一个 hack 类禁用了控件上的样式,需要手动指定样式并要求更新。
  • 您可以将其附加到 .TagObject 属性。
  • @UmairAhmed Data 不是你我想象的那样。 TagObject 会做你想做的事。很抱歉误导了你。

标签: delphi firemonkey-fm2


【解决方案1】:

如果你想将一个对象“附加”到 TControl,TControl 的父类 TFmxObject 引入了存储任何对象值的 .TagObject 属性。

除了使用此属性之外,您还可以使用 .Tag 属性将类型转换为 NativeInt 和您想要的类类型,例如:TreeViewItem1.Tag := NativeInt(List);和列表:= TList(TreeViewItem1.Tag);

【讨论】:

  • 标签对 ARC 不好,我猜这就是 TagObject 存在的原因
  • @DavidHeffernan - 不,TagObject 在 FMX 成为 FMX 之前就存在了。还有一个TagFloat...
  • @ChrisRolliston TagFloat?呃,为什么?!!
  • 我使用的是 XE8,只有一个 .Tag 属性。适用于 Windows 和 OS-X,但不适用于 iOS(不断给我访问冲突)。
【解决方案2】:

在“小“g””通用方式中,FMX 控件的Data 属性应该获取或设置控件的核心值。在TImage 的情况下,这将是显示的位图,在TEdit 的情况下将是文本等等。因此,它的目的与 VCL 树视图项的 Data 属性完全不同,后者是从对象中挂起任意数据。

正如 pani 正确回答的那样,如果您想挂起对 FMX 树视图项的任意对象引用,那么您可以使用 TagObject也就是说,尽管对 FMX 对正确 OOP 行为的影响(参见 here)感到恼火,但如果您正在动态创建树视图项目,那么更好的方法可能是派生自定义 TTreeViewItem 后代:

uses System.Generics.Collections;

type
  TRoomTreeViewItem = class(TTreeViewItem)
    RoomList: TList<TRoom>; //better use a generic than non-generic list as mentioned above
  end;

或者,如果房间列表的生命周期与其关联的树视图项的生命周期相同,您实际上可以将列表封装在项目中:

type
  TRoomTreeViewItem = class(TTreeViewItem)
  strict private
    FRoomList: TObjectList<TRoom>;
    function GetRoom(Index: Integer): TRoom;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
    function GetEnumerator: TEnumerator<TRoom>;
    function AddRoom: TRoom;
    property Rooms[Index: Integer] read GetRoom;
  end;

constructor TRoomTreeViewItem.Create(AOwner: TComponent);
begin
  inherited;
  FRoomList := TObjectList<TRoom>.Create;
end;

destructor TRoomTreeViewItem.Destroy;
begin
  FRoomList.Free;
  inherited;
end;

function TRoomTreeViewItem.GetEnumerator: TEnumerator<TRoom>;
begin
  Result := FRoomList.GetEnumerator;
end;

function TRoomTreeViewItem.GetRoom(Index: Integer): TRoom;
begin
  Result := FRoomList[Index];
end;

function TRoomTreeViewItem.AddRoom: TRoom;
begin
  Result := TRoom.Create;
  FRoomList.Add(Result);
end;

有些人可能会认为第二个变体是非 UI 与 UI 代码的可怕混合——尽管 YMMV,但我个人并不反对它(事实上,这就是我建议它的原因)。

【讨论】:

  • 我已经尝试过了,并且遇到了同样令人难以置信的样式问题,但链接的文章确实证明了它们对缓解问题的深刻见解。我以另一种方式解决了它们,但如果只需要附加一个对象,我仍然认为更大的可用性是不值得的,否则我无法反驳你的论点。
  • @UmairAhmed - 直接从 TTreeViewItem 派生时遇到样式问题...?
  • 是的,我做到了,我通过在新构造函数中传递和设置父级解决了这个问题,它可以在 BeginUpdate/EndUpdate 块中完成创建的地方工作,否则它需要手动设置为默认值treeviewitemstyle 让它们工作。我没有寻找受保护的 FStyleLookup。
  • @UmairAhmed - 啊,好的。这确实是另一个错误(并且影响的不仅仅是我发现的 TTreeViewItem ......)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-02-09
  • 1970-01-01
  • 1970-01-01
  • 2021-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多