Как прикрепить объект любого типа с помощью TControl?
Я хочу добавить TList с TTreeViewItem и объект пользовательского класса (TRoom) с другим. В delphi 2007 появилось поле "Данные" типа Pointer, которое было заменено на TValue, которое я не знаю, как использовать. Я искал в Интернете некоторые утверждения, что он не может обрабатывать пользовательские типы в настоящее время.
Может кто-нибудь придумать способ добиться этого, кроме как взломать урок?
Например, следующий код формы должен работать правильно:
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.
2 ответа
Если вы хотите "прикрепить" объект к TControl, родительский класс TControl TFmxObject представляет свойство.TagObject, в котором хранится любое значение объекта.
Помимо использования этого свойства вы также можете использовать свойство.Tag с приведением типов в NativeInt и типом нужного вам класса, например: TreeViewItem1.Tag:= NativeInt(List); и список:= TList(TreeViewItem1.Tag);
В "маленьком" g "родовом стиле, Data
свойство элемента управления FMX должно получить или установить значение ядра элемента управления. В TImage
если это будет отображаемое растровое изображение, для TEdit
текст и тд. Таким образом, его назначение полностью отличается от Data
свойство элемента представления дерева VCL, которое должно повесить произвольную часть данных от объекта.
Как правильно ответит pani, если вы хотите повесить произвольную ссылку на объект на элемент дерева FMX, вы можете использовать TagObject
, Тем не менее, несмотря на раздражения, связанные с использованием FMX правильного поведения ООП (см. Здесь), если вы создаете элементы в виде дерева динамически, то лучшим способом может быть получение пользовательского 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;
Однако некоторые люди могут считать второй вариант ужасным соединением не-пользовательского интерфейса с кодом пользовательского интерфейса - лично я не против (действительно, именно поэтому я и предложил), хотя YMMV.