Reputation: 247
Hi i've a project that uses the VirtualStringTree , with this Record :
type
TStudentsSession = record
StudentName : String;
StudentClass : String;
StudentHandRaised:Boolean;
end;
And i've these Procedures :
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;
We Have these 4 Students in Order:
What i want is this :
1 : StudentB raises his Hand :
2 : StudentC raises his Hand :
StudentC will not Jump on StudentB ( Because StudentB is still raising his Hand )
3 : StudentD raises his Hand :
StudentC will not Jump on StudentB or StudentC ( Because both are still raising their Hands )
4 : StudentB withdraws his hand :
StudentB will be moved to the last position
I tried to use this procedure :
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;
Thank you all
Upvotes: 0
Views: 1375
Reputation: 964
Whenever you want to implement a custom sort order in VirtualStringTree
, you should use OnCompareNodes
event. Here's the simple example based on your code:
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;
Note that I've written this without testing (from my memory), so you may have to tweak it a bit to suit your needs. For better understanding how this works, check the documentation.
If you include toAutoSort
in the Options.AutoOptions
set (set it to True
in the Object Inspector), this event is automatically called every time a node is inserted or deleted, or the node's Text is changed. However, if sorting depends on other elements of node data (your TStudentsSession record in this case), you will have to manually call SortTree
method.
Another simple way of sorting the tree is by using Header.SortColumn
, but in that case you're limited to a single column.
Upvotes: 2