Как получить количество отображаемых узлов в TVirtualStringTree? - PullRequest
2 голосов
/ 07 марта 2019

Мне нужно показать длинную таблицу БД в TVirtualStringTree (например, 50000 записей).Чтобы уменьшить время выполнения запроса, я ограничиваю количество записей только теми, которые фактически отображаются в дереве.Ниже приведен фрагмент кода обработки OnGetText.Проблема в том, что VisibleCount возвращает 50000 вместо 20-30, что разрушает этот подход.Есть ли способ сделать это правильно?

procedure TContactsFrame.vstContactsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; 
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
begin
  if vstContacts.GetNodeLevel(Node) = 0 then
    CellText := 'Group'
  else if vstContacts.GetNodeLevel(Node) = 1 then
  begin
    if Contacts[Node.Index].Index = -1 then
    begin
      // getting DB table values of visible records only
      GetContacts(Node.Index + 1, Node.Index + 1 + vstContacts.VisibleCount, Contacts);
    end;
    CellText := Contacts[Node.Index].Name;
  end;
end;

Ответы [ 2 ]

2 голосов
/ 07 марта 2019

VisibleCount дает количество узлов с установленным флагом vsVisible (видимое значение не скрыто).

Чтобы перечислить узлы, отображаемые в данный момент в виде дерева, вы можете использовать TopNode и BottomNode аналогично следующему:

var
  Run, LastNode: PVirtualNode;
begin
  LastNode := Treeview.GetNextVisible(Treeview.BottomNode);
  Run := Treeview.TopNode;

  while Assigned(Run) do
  begin
    // your processing here

    Run := Treeview.GetNextVisible(Run);
    if Run = LastNode then
      Break;
  end;
end;
1 голос
/ 07 марта 2019

Чтобы найти количество отображаемых узлов, вам нужно написать собственную функцию, но в этом случае должно быть достаточно получить первый и последний отображаемый узел, используя TopNode и BottomNode или GetFirst и GetLast если они не существуют.

procedure TContactsFrame.vstContactsGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; 
  Column: TColumnIndex; TextType: TVSTTextType; var CellText: string);
var
  lTopNode, lBottomNode : PVirtualNode;
begin
  case vstContacts.GetNodeLevel(Node) of
    0 : CellText := 'Group'
    1 : begin
          if Contacts[Node.Index].Index = -1 then
          begin
            // getting DB table values of visible records only
            lTopNode := vstContacts.TopNode;
            if not Assigned(lTopNode) then
              lTopNode := vstContacts.GetFirst;
            lBottomNode := vstContacts.BottomNode;
            if not Assigned(lBottomNode) then
              lBottomNode := vstContacts.GetLast;
            GetContacts(lTopNode.Index + 1, lBottomNode.Index + 1, Contacts);
          end;
          CellText := Contacts[Node.Index].Name;
        end;
  end;
end;

Однако я должен сказать, что это не самое эффективное решение, потому что вы будете выполнять тысячи запросов при случайной прокрутке дерева.Во всяком случае, я бы умножил количество найденных контактов, чтобы вам не приходилось так часто запускать новые запросы.

...