Если вам нужно отобразить длинную таблицу из базы данных в TVirtualStringTree (например, 50000 записей), чтобы снизить время выполнения запроса, вы можете ограничить количество записей только теми, которые фактически отображаются в дереве. Однако, если использовать свойство VisibleCount, оно возвращает общее количество записей, а не те, которые фактически отображаются, что делает этот подход неэффективным.
В этом материале мы рассмотрим, как правильно определить количество отображаемых узлов в TVirtualStringTree, чтобы оптимизировать отображение больших таблиц.
Проблема
Рассмотрим следующий код, в котором пытаются получить значения из базы данных только для видимых записей:
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;
Проблема заключается в том, что VisibleCount возвращает общее количество записей (50000), а не те 20-30, которые фактически отображаются, что делает этот подход неэффективным.
Решение
Чтобы определить количество отображаемых узлов, вам необходимо написать собственную функцию. В данном случае достаточно получить первый и последний отображаемый узел с помощью свойств 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;
Однако, этот подход все еще может привести к большому количеству запросов при прокрутке дерева. Чтобы этого избежать, вы можете увеличить количество получаемых контактов, чтобы не запускать новые запросы так часто.
Альтернативный подход
Чтобы перечислить узлы, которые фактически отображаются в дереве, вы можете использовать TopNode и BottomNode следующим образом:
var
Run, LastNode: PVirtualNode;
begin
LastNode := Treeview.GetNextVisible(Treeview.BottomNode);
Run := Treeview.TopNode;
while Assigned(Run) do
begin
// ваша обработка здесь
Run := Treeview.GetNextVisible(Run);
if Run = LastNode then
Break;
end;
end;
Этот подход позволяет перечислить все отображаемые узлы и обработать их по одному.
В заключение, при работе с большими таблицами в TVirtualStringTree важно правильно определять количество отображаемых узлов, чтобы оптимизировать отображение данных и выполнение запросов. В данной статье мы рассмотрели два подхода к решению этой проблемы и обсудили их преимущества и недостатки.
Материал описывает проблему оптимизации отображения больших таблиц в TVirtualStringTree и предлагает решения для определения количества фактически отображаемых узлов, чтобы повысить эффективность работы с большими данными.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.