2013-11-22 3 views
3

TTreeViewItem 및 사용자 정의 클래스 (TRoom)의 객체가있는 TList를 다른 객체에 추가하려고합니다. 델파이 2007에는 포인터 타입의 'Data'필드가 있는데 여기에는 TValue로 대체되었습니다. 사용법에 관해서는 알지 못합니다. 나는 그것이 당분간 사용자 지정 형식을 처리 할 수 ​​없다는 것을 언급하면서 인터넷을 검색했습니다.TControl을 사용하여 모든 유형의 객체를 연결하는 방법은 무엇입니까?

해킹 클래스를 만드는 경우를 제외하고는 누군가 달성 할 수있는 방법을 고안 할 수 있습니까?

예를 들어, 다음과 같은 형태의 코드가 제대로 실행해야합니다 : -

당신은 TControl의에 개체를 "연결"하려면
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. 
+0

'TValue'는 변형 타입입니다. 'Data.AsObject'를 사용하십시오. –

+0

이 작동하지 않습니다. 컴파일러 오류'호환되지 않는 타입 ... '이 타입 캐스트가없고'잘못된 타입 변환 '이 없습니다. –

+0

@JerryDodge 해킹 클래스는 컨트롤의 스타일을 비활성화하여 수동 스타일 지정이 필요하며 업데이트가 필요합니다. –

답변

2

은 TControl의 부모 클래스 TFmxObject가 개체 값을 저장하는 .TagObject 속성을 소개합니다.

이 속성 외에도 .Tag 속성을 사용하여 NativeInt 및 원하는 클래스 유형으로 typecasting 할 수 있습니다. 예를 들면 다음과 같습니다. TreeViewItem1.Tag : = NativeInt (List); 및 목록 : = TList (TreeViewItem1.Tag);

+1

TagObject가 존재하는 이유가 ARC에있어 좋지 않습니다. –

+0

@DavidHeffernan - 아니요, TagObject가 FMX 이전에 존재했습니다. 'TagFloat'도 있습니다 ... –

+0

@ChrisRolliston TagFloat? 왜? !! –

1

'작은 "g"일반 형식에서 FMX 컨트롤의 Data 속성은 컨트롤의 핵심 값을 가져 오거나 설정해야합니다. TImage 경우에는 비트 맵이 표시되고 TEdit이면 텍스트가 표시됩니다. 따라서 그 목적은 객체의 임의의 데이터를 걸러내는 VCL 트리 뷰 항목의 속성과 완전히 다릅니다.

pani가 올바르게 대답 할 때 FMX 트리보기 항목에 임의의 개체 참조를 걸려면 TagObject을 사용할 수 있습니다. 말했다 , 적절한 OOP의 행동 FMX의 bodging 관련된 자극 (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에도 불구하고 나는 그것을 반대하지 않습니다. (실제로 그것이 내가 제안한 이유입니다.)

+0

나는 그것을 시도해 보았고 같은 생각을 부끄럽게 만드는 스타일링 문제에 빠졌습니다. 링크 된 기사는 완화에 대한 통찰력을 증명합니다. 나는 다른 방법으로 해결했지만 여전히 유일한 대상을 부착해야한다면 큰 유용성이 추가 마일의 가치가 없다고 생각합니다. 그렇지 않으면 당신의 주장을 논박 할 수 없습니다. –

+0

@UmairAhmed - TTreeViewItem에서 직접 파생되면 스타일링 문제가 발생합니다 ...? –

+0

네, 새로운 생성자에서 부모를 전달하고 설정하여 해결했습니다. BeginUpdate/EndUpdate 블록에서 생성이 수행되는 곳에서 작동했습니다. 그렇지 않으면 수동으로 기본 treeviewitemstyle을 사용하여 작동하게했습니다. 나는 보호 된 FStyleLookup을 찾지 않았다. –