Question

I want to add a TList with a TTreeViewItem and a custom class (TRoom)'s object with another. In delphi 2007 there was a field 'Data' of Pointer type which has been replaced with a TValue here which I don't know as to how to use. I have searched the internet with some stating that it can't handle custom types for the time being.

Can somebody devise a way to achieve this, except for making a hack class?

For example, the following form code should run properly:-

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.
Was it helpful?

Solution

If you want to "attach" an object to TControl, TControl's parent class TFmxObject introduces the .TagObject property that stores any object value.

Besides using this property you can also use the .Tag property with typecasting into NativeInt and your wanted class type, for example: TreeViewItem1.Tag := NativeInt(List); and List := TList(TreeViewItem1.Tag);

OTHER TIPS

In in a 'small "g"' generic fashion, the Data property of a FMX control should get or set the control's core value. In a TImage case this will be the bitmap displayed, for a TEdit the text and so on. As such, its purpose is completely different to the Data property of a VCL tree view item, which is to hang an arbitrary piece of data off of the object.

As pani rightly answers, if you want to hang an arbitrary object reference to a FMX tree view item, then you can use TagObject. That said, and notwithstanding irritations concerning FMX's bodging of proper OOP behaviour (see here), if you are creating tree view items dynamically then a better way might be to derive a custom TTreeViewItem descendant:

uses System.Generics.Collections;

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

Or, if the lifetime of a room list is the same as the lifetime of the tree view item it is associated with, you could actually encapsulate the list in the item:

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;

Some people may consider the second variant a terrible conflation of non-UI with UI code however - personally I don't oppose it (indeed, that's why I've suggested it), though YMMV.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top