如何在 TTreeView的 Node 里关联自己的数据 |
|
pcplayer99
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:146 回覆:790 積分:632 註冊:2003-01-21 發送簡訊給我 |
如何在 TTreeView的 Node 里关联自己的数据 使用 TreeView,通常想把自己的数据关联到Node上去。比如,选中一个Node,就显示一串对应这个Node的文字。 我搜索了一下,网上讲这个问题的文章,通常的做法是利用TTreeNode.Data来保存一个外部的Object的Pointer. 大概的代码如下: 先定义一个用来保存你自己的数据的类:
type TPropStore = class (TObject) private { Private declarations } public { Public declarations } AUserString: String; //add your own properties to this object constructor Create; end; 然后,这样把你自己的数据放进TTreeView里去: procedure TForm1.AddItem; var AProp: TPropStore; begin AProp:= TPropStore.Create; TreeView1.Items.AddObject(nil,'Item',AProp); <---用 AddObject 方法来产生一个新的Node,顺便把一个外部的对象的Pointer保存进去。 AProp.AUserString:='Hello,world!'; end; 然后,要从选中的Node读回来自己的数据,这样做: procedure TForm1.SpeedButton4Click(Sender: TObject); var SelNode : TTreeNode; begin SelNode:=TreeView1.Selected; if SelNode<>nil then begin Form2.Edit1.Text:=SelNode.Text; Form2.Edit2.Text:=TPropStore(SelNode.Data).AUserString; <---这里,把SelNode.Data这个Pointer强制转换为TPropStore类型,然后读它的AUserString if Form2.ShowModal=mrOk then begin SelNode.Text:=Form2.Edit1.Text; TPropStore(SelNode.Data).AUserString:=Form2.Edit2.Text; end; end else ShowMessage('Select an item in the treeview before trying to edit'); end; 以上代码来自Borland Code Center里的一个例子。Written by Dr Steve Evans (steve@lociuk.com)但是,我不喜欢这种做法。我不喜欢明显地看到Pointer,尽管一个Object就是一个Pointer。 一般来说,我自己用到一个TreeView,多半就是用它来保存同样的一类数据。因此,我用了另外一个办法:继承TTreeNode,产生一个可以包含自己的数据的新的类: type TMyNode = class (TTreeNode) private FID: Integer; protected procedure SetID(const Value: Integer); virtual; function GetID: Integer; virtual; public property ID: Integer read GetID write SetID; end; 然后,我就可以任意在TreeView里用Node来关联/保存我自己的数据了。首先,生成一个Node: MyNode:=TreeView1.Items.Add(nil,Fields[2].AsString) as TMyNode; MyNode.ID:=ID; 这里,直接用TTreeView.Items.Add增加一个Node,和普通的操作完全一样,只不过这个新增加的Node是一个可以包含我自己的数据的TMyNode 要把自己的数据从Node读出来就更简单了: ID:=TMyNode(TreeView1.Selected).ID;直接把选中的TTreeNode转化为TMyNode,然后就可以读到TMyNode里的自己的数据了。 这样做,没有Pointer的操作,完全是对象的操作,看起来更舒服,也更直观。 究竟哪个方法更好,请高人指点。 |
Chance36
版主 ![]() ![]() ![]() ![]() ![]() ![]() 發表:31 回覆:1033 積分:792 註冊:2002-12-31 發送簡訊給我 |
pcplayer99 你好 你有測試過了嗎?
我測的結果 底下一行編譯就不過了 MyNode:=TreeView1.Items.Add(nil,Fields[2].AsString) as TMyNode; // 編譯不過 MyNode.ID:=ID; 改成如下 (強制轉型):編譯ok 了 後續的操作好像也沒問題,但別高興的太早 MyNode:=TMyNode(TreeView1.Items.Add(nil,Fields[2].AsString) ); // 編譯OK MyNode.ID:=ID; 當程式要結束時,程式就會出現 [Invalid Pointer Operation] 的錯誤 主要是TreeView1.Items.Add(nil,Fields[2].AsString) 建立的object 是TTreeNode 假設TTreeNode位用100Byte記憶體,而自定義的TMyNode 至少佔用104Byte,將TTreeNode 強制轉型成子類別 那TMyNode.ID 到底會存取到什麼地方呢?這應該就是系統出錯的地方;物件的轉型只能將子類別轉型成父類別吧!! 若強制將父類別轉型為子類別,出錯就只能怪自己了。 個人意見,若有謬誤,請勿見怪! |
pcplayer99
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:146 回覆:790 積分:632 註冊:2003-01-21 發送簡訊給我 |
|
pcplayer99
尊榮會員 ![]() ![]() ![]() ![]() ![]() ![]() 發表:146 回覆:790 積分:632 註冊:2003-01-21 發送簡訊給我 |
本站聲明 |
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。 2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。 3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇! |