//
// die üblichen Verdächtigen des VST...
//
procedure TfrmMain.vstTestGridGetNodeDataSize(Sender: TBaseVirtualTree;
var NodeDataSize: Integer);
begin
inherited;
TVirtualStringTree(Sender).NodeDataSize := SizeOf(TGridNodeData);
end;
procedure TfrmMain.vstTestGridInitNode(Sender: TBaseVirtualTree; ParentNode,
Node: PVirtualNode;
var InitialStates: TVirtualNodeInitStates);
var
NodeData: PGridNodeData;
begin
inherited;
NodeData := Sender.GetNodeData(Node);
if Assigned(NodeData)
then
NodeData^ := Node.
Index + 1;
// Anzeige startet bei 1, nicht 0
end;
procedure TfrmMain.vstTestGridGetText(Sender: TBaseVirtualTree;
Node: PVirtualNode; Column: TColumnIndex; TextType: TVSTTextType;
var CellText:
String);
var
NodeData: PGridNodeData;
DatabaseRecord: PDatabaseRecord;
function GetDBRecord: Boolean;
begin
// hier wird der Eintrag aus der Datenbank geholt
...
Result := Assigned(DatabaseRecord);
end;
begin
inherited;
NodeData := Sender.GetNodeData(Node);
if Assigned(NodeData)
then
begin
CellText := '
-';
// default for invalid data
case Column
of
0: CellText := IntToStr(NodeData^);
1:
if GetDBRecord
then
CellText := DatabaseRecord^.MeinDatenbankFeld1;
2:
if GetDBRecord
then
CellText := DatabaseRecord^.MeinDatenbankFeld2;
4:
if GetDBRecord
then
CellText := DatabaseRecord^.MeinDatenbankFeld3;
...
end;
end;
end;
procedure TfrmMain.vstTestGridHeaderClick(Sender: TVTHeader;
Column: TColumnIndex; Button: TMouseButton; Shift: TShiftState; X,
Y: Integer);
begin
inherited;
// handle sorting changes
if Button = mbLeft
then
begin
vstTestGrid.BeginUpdate;
try
with Sender
do
begin
if SortColumn <> Column
then
SortColumn := Column;
if SortDirection = sdAscending
then
SortDirection := sdDescending
else
SortDirection := sdAscending;
QuickSortTree(True);
end;
finally
vstTestGrid.EndUpdate;
end;
end;
end;
//
// jetzt wird es interessant
//
procedure MyUpdateGrid;
begin
BeginUpdate;
try
if (DBCount > 0)
then
begin
if (Header.SortDirection = sdAscending)
then
RootNodeCount := DBCount
// Aufsteigend, wir müssen nichts machen
else
begin
if (DBCount > VSTCount)
then
begin
for i := VSTCount+1
to DBCount
do
begin
Node := vstTestGrid.InsertNode(
nil, amInsertBefore);
// vorher einfügen
if Assigned(Node)
then
begin
vstTestGrid.ReinitNode(Node, False);
// Node Initialisierung erzwingen
Int64(vstTestGrid.GetNodeData(Node)^) := i;
// korrekten Wert zuweisen (wäre sonst 1, wegen vstTestGridInitNode)
end;
end;
end;
end;
end
else
...
finally
vstTestGrid.EndUpdate;
end;
end;
//
// was noch fehlt: die "Sortierung"
//
procedure TfrmMain.QuickSortTree(ForceSort: Boolean = False);
var
Grid: TVirtualStringTree;
Node: PVirtualNode;
sd: TSortDirection;
IndexNo: Int64;
procedure SwapSelection;
begin
// hier gehe ich alle Nodes durch, um die Auswahl (Selection)
// des Benutzers umzukehren
LeftNode := Grid.GetFirst;
RightNode := Grid.GetLast;
if not (Assigned(LeftNode)
and Assigned(RightNode))
then
Exit;
// get starting values
LeftValue := Int64(Grid.GetNodeData(LeftNode)^);
RightValue := Int64(Grid.GetNodeData(RightNode)^);
// swap values if needed
if LeftValue > RightValue
then
begin
i := RightValue;
RightValue := LeftValue;
LeftValue := i;
end;
// Note: We use LeftValue and RightValue to sort only up to the first half
// of the tree (otherwise we would reset our own swap)
// iterate through the tree nodes
while (Assigned(LeftNode)
and Assigned(RightNode))
and
((RightNode <> LeftNode)
and (LeftValue < RightValue))
do
begin
// get current selection states
LeftSelected := vsSelected
in LeftNode.States;
RightSelected := vsSelected
in RightNode.States;
// swap selection
if (LeftSelected <> RightSelected)
then
begin
Grid.Selected[LeftNode] := RightSelected;
Grid.Selected[RightNode] := LeftSelected;
end;
// get next nodes
LeftNode := LeftNode.NextSibling;
RightNode := RightNode.PrevSibling;
// adjust iteration helper
Inc(LeftValue);
Dec(RightValue);
end;
end;
begin
Grid := vstTestGrid;
Assert(Assigned(Grid));
// set sorting options
sd := Grid.Header.SortDirection;
if (sd = sdAscending)
and (
not ForceSort)
then
Exit;
if sd = sdAscending
then
IndexNo := 1
else
IndexNo := Grid.RootNodeCount;
// assign new index values
Node := Grid.GetFirst;
while Assigned(Node)
do
begin
Int64(Grid.GetNodeData(Node)^) := IndexNo;
if sd = sdAscending
then
Inc(IndexNo)
else
Dec(IndexNo);
Node := Grid.GetNext(Node);
end;
// swap node selection
if (Grid.SelectedCount > 0)
then
SwapSelection;
end;