2016-07-30 4 views
1

Пожалуйста, обратите внимание реветь код:GetText из TVirtualStringTree становится срабатывает несколько раз

unit Unit2; 

interface 

uses 
    Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, 
    Vcl.Controls, Vcl.Forms, Vcl.Dialogs, VirtualTrees, Vcl.StdCtrls; 

type 
    TTreeData = record 
    Fields: array of String; 
    end; 
    PTreeData = ^TTreeData; 

const 
    szVirtualTree = SizeOf(TTreeData); 

type 
    TForm2 = class(TForm) 
    tree: TVirtualStringTree; 
    Button1: TButton; 
    procedure treeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; 
     Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); 
    procedure treeGetNodeDataSize(Sender: TBaseVirtualTree; 
     var NodeDataSize: Integer); 
    procedure Button1Click(Sender: TObject); 
    private 
    { Private declarations } 
    public 
    { Public declarations } 
    end; 

var 
    Form2: TForm2; 

implementation 

{$R *.dfm} 

procedure TForm2.Button1Click(Sender: TObject); 
var 
    LTreeData: PTreeData; 
    Node: PVirtualNode; 
    cols, rows, col, row: Integer; 
begin 
    cols:= 2; 
    rows:= 2; 

    Tree.Header.Columns.Clear; 
    if cols > 0 then 
    for col := 0 to cols - 1 do 
     with Tree.Header.Columns.Add do 
     begin 
      Text:= 'H' + IntToStr(col); 
      Width:= 80; 
     end; 

    Tree.Clear; 
    Tree.BeginUpdate; 

    if (cols> 0) and (rows > 0) then 
    for row := 0 to rows - 1 do 
     begin 
     Node:= Tree.AddChild(nil,nil); 
     Tree.ValidateNode(Node,False); 

     LTreeData:= Tree.GetNodeData(Node); 
     SetLength(LTreeData^.Fields, cols); 

     if cols > 0 then 
      for col := 0 to cols - 1 do 
      LTreeData^.Fields[col]:= '[' + inttostr(col) + ',' + inttostr(row) + ']'; 
     end; 

    Tree.EndUpdate; 
end; 

procedure TForm2.treeGetNodeDataSize(Sender: TBaseVirtualTree; 
    var NodeDataSize: Integer); 
begin 
    NodeDataSize:= szVirtualTree; 
end; 

procedure TForm2.treeGetText(Sender: TBaseVirtualTree; Node: PVirtualNode; 
    Column: TColumnIndex; TextType: TVSTTextType; var CellText: string); 
var 
    LTreeData: PTreeData; 
begin 
    LTreeData:= Sender.GetNodeData(Node); 
    CellText:= LTreeData^.Fields[Column]; 
    showmessage(CellText); 
end; 

end. 

После нажатия кнопки получает нажимается сообщения я получаю:

[0,0] 
[0,0] 
[0,0] 
[0,0] 
[1,0] 
[1,0] 
[1,0] 
[1,0] 
[0,1] 
[0,1] 
[0,1] 
[0,1] 
[1,1] 
[1,1] 
[1,1] 
[1,1] 

В основном GetText запускается 4 раз для каждого узла и каждого столбца.

Почему не срабатывает только один раз? Как это: [0,0] [1,0] [0,1] [1,1]

enter image description here

+3

Это по дизайну. Обратите внимание на параметры. Обработчик событий запускается отдельно для разных столбцов и типа текста. –

+2

Вам действительно нужно лучше вести журнал, чем 'ShowMessage'. Бросьте вызов «AllocConsole» и используйте «WriteLn». Или просто 'OutputDebugString'. –

+0

Я никогда не использую этот инструмент до сих пор Дэвид! – REALSOFO

ответ

2

управление использует так называемые виртуальные парадигму. Автор Mike Lischke explains this like so:

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

Управление не отслеживает заголовки узлов. Всякий раз, когда он должен знать их, он запускает метод OnGetText. Элемент управления не кэширует, не запоминает заголовки узлов. Поэтому, если несколько частей управляющего кода зависят от заголовка, тогда событие будет вызываться несколько раз для одного и того же узла.

Поведение, которое вы наблюдаете, является абсолютно нормальным и полностью ожидаемым. Работа вашего обработчика OnGetText должна дать текст узла. Не волнуйтесь, если задан тот же вопрос дважды. Просто убедитесь, что вы даете один и тот же ответ каждый раз!

+0

Хорошо ответил! Спасибо, Дэвид! – REALSOFO