Delphi VirtualStringTree和一个队列

时间:2013-09-01 21:42:05

标签: delphi virtualtreeview tvirtualstringtree

嗨我有一个使用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名学生:

  • StudentA
  • StudentB
  • StudentC
  • StudentD

我想要的是:

1:学生B举手:

  • StudentB
  • StudentA
  • StudentC
  • StudentD

2:StudentC举手:

  • StudentB
  • StudentC
  • StudentA
  • StudentD

StudentC不会跳到学生B上(因为学生B还在举手)

3:StudentD举手:

  • StudentB
  • StudentC
  • StudentD
  • StudentA

StudentC不会跳过StudentB或StudentC(因为他们两人仍在举手)

4:StudentB退出了手:

  • StudentC
  • StudentD
  • StudentA
  • 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;

谢谢大家

1 个答案:

答案 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,但在这种情况下,您只能使用一列。