假设我有这个节点数据记录:
Type
PPerson = ^TPerson;
TPerson = record
Name: String;
Age: Integer;
SomeBool: Boolean;
end;
要填充我的VirtualStringTree,我会这样做:
Procedure AddToTree(Person: TPerson);
Var
Node: PVirtualNode;
Data: PPerson;
Begin
Node := VT.AddChild(nil);
Data := VT.GetNodeData(Node);
Data.Name := Person.Name;
Data.Age := Person.Age;
Data.SomeBool := Person.SomeBool;
End;
Procedure TMyForm.MyButtonClick(Sender: TObject);
Var
Person: TPerson;
Begin
Person.Name := 'Jeff';
Person.Age := 16;
Person.SomeBool := False;
AddToTree(Person);
End:
现在,虽然这很好用,但我想简化它,所以每当我向记录中添加新字段时,我都不会修改AddToTree方法。
所以我尝试了这个:
Procedure AddToTree(Person: TPerson);
Begin
VT.AddChild(nil,@Person);
End;
这个编译,但它似乎PVirtualNode
没有获取数据,因为我的VT没有显示任何内容,并且当打破OnGetText事件时,我看到变量是空的
我做错了什么? :)
答案 0 :(得分:5)
记录支持赋值运算符:
procedure AddToTree(const Person: TPerson);
var
Node: PVirtualNode;
Data: PPerson;
begin
Node := VT.AddChild(nil);
Data := VT.GetNodeData(Node);
Data^ := Person;
end;
答案 1 :(得分:3)
您没有阅读手册:)
好的,在这种情况下,来源是手册 - 引自AddChild()
来源:
UserData可用于将用户数据区的前4个字节设置为可以使用的初始值 在OnInitNode中也会导致触发OnFreeNode事件(如果<> nil),即使该节点还没有 “正式”初始化。
以下它并不意味着以您使用它/期望它的方式使用。
BTW为什么要复制数据?为什么没有
type
PTreeData = ^TTreeData;
TTreeData = record
Data: PPerson;
end;
并分配记录New()
将它们保存在树中,然后Dispose()
清除树时?
答案 2 :(得分:3)
使用记录作为数据持有者时,在VTV中存储数据的最佳方法是仅存储指向记录的指针,而记录本身则单独存储在列表/数组中。当可视组件实际上不拥有数据时,这也对应于虚拟和MVC范例。 IOW,添加记录的方案是:
删除记录的方案是:
答案 3 :(得分:0)
还有一个“我在提出问题后2分钟找到答案” - 多么羞辱...... :(
无论如何,所以 - 这可以通过使用CopyMemory来完成,如下所示:
Procedure AddToTree(Person: TPerson);
Var
Data: PPerson;
Node: PVirtualNode;
Begin
// add node
Node := VT.AddChild(nil);
// Get data of the node
Data := VT.GetNodeData(Node);
// Copy the Person stuff to the Node's data.
CopyMemory(Data,@Person,SizeOf(Person));
End;