嗨我有一个使用VirtualStringTree的项目,带有此记录:
type
TStudentsSession = record
StudentName : String;
StudentClass : String;
StudentHandRaised:Boolean;
end;
我有这些程序:
Procedure TMainForm.StudentHandRaised(AStudentName: String)
var
Node: PVirtualNode;
Data: ^TStudentsSession;
begin
Node := StudentsVst.GetFirst;
while Node <> nil do
begin
Data := StudentsVst.GetNodeData(Node);
if Data.StudentName = AStudentName then
begin
Data.StudentHandRaised := True;
Break;
end;
Node := StudentsVst.GetNext(Node);
end;
end;
Procedure TMainForm.StudentHandsDown(AStudentName: String)
var
Node: PVirtualNode;
Data: ^TStudentsSession;
begin
Node := StudentsVst.GetFirst;
while Node <> nil do
begin
Data := StudentsVst.GetNodeData(Node);
if Data.StudentName = AStudentName then
begin
Data.StudentHandRaised := False;
Break;
end;
Node := StudentsVst.GetNext(Node);
end;
end;
我们按顺序安排了这4名学生:
我想要的是:
1:学生B举手:
2:StudentC举手:
StudentC不会跳到学生B上(因为学生B还在举手)
3:StudentD举手:
StudentC不会跳过StudentB或StudentC(因为他们两人仍在举手)
4:StudentB退出了手:
StudentB将移至最后一个位置
我尝试使用此程序:
procedure TMainForm.ReArrangeStudents;
var
Node, PreviNode: PVirtualNode;
Data: ^TStudentsSession;
begin
Node := StudentsVst.GetFirst;
while Node <> nil do
begin
Data := StudentsVst.GetNodeData(Node);
if Data.StudentHandRaised then
PreviNode := StudentsVst.GetPrevious(Node, False)
else
PreviNode := StudentsVst.GetNext(Node);
StudentsVst.MoveTo(Node, PreviNode, amInsertBefore, False);
Node := StudentsVst.GetNext(Node);
end;
end;
谢谢大家
答案 0 :(得分:2)
每当您想在VirtualStringTree
中实施自定义排序顺序时,都应使用OnCompareNodes
事件。以下是基于您的代码的简单示例:
procedure TMainForm.StudentsVstCompareNodes(Sender: TBaseVirtualTree; Node1, Node2: PVirtualNode; Column: TColumnIndex; var Result: Integer);
var
Data1, Data2: ^TStudentsSession;
begin
Data1 := Sender.GetNodeData(Node1);
Data2 := Sender.GetNodeData(Node2);
// If both students have their hands raised, compare by student name
if Data1.StudentHandRaised and Data2.StudentHandRaised then
begin
Result := CompareStr(Data1.StudentName, Data2.StudentName);
end
else
begin
// If only one student has his/her hand raised, move him/her before the other one
if Data1.StudentHandRaised and (not Data2.StudentHandRaised) then
Result := 1
else if (not Data1.StudentHandRaised) and Data2.StudentHandRaised then
Result := -1
// If both students have their hands down, compare by student name
else
Result := CompareStr(Data1.StudentName, Data2.StudentName);
end;
end;
请注意,我是在没有测试的情况下(从我的记忆中)编写的,因此您可能需要稍微调整一下以满足您的需求。为了更好地理解其工作原理,请查看文档。
如果在toAutoSort
集中包含Options.AutoOptions
(在对象检查器中将其设置为True
),则每次插入或删除节点时都会自动调用此事件,或者节点的文本已更改。但是,如果排序依赖于节点数据的其他元素(在这种情况下是您的TStudentsSession记录),则必须手动调用SortTree
方法。
另一种对树进行排序的简单方法是使用Header.SortColumn
,但在这种情况下,您只能使用一列。