2017-02-12 6 views
1

У меня есть задание в «управлении проектами». Я должен назначить модули, которые также могут быть подмодулями, поэтому я хочу добавить рекурсивные подмодули к модулям.Delphi TTreeNode рекурсивно присоединяет дочерние узлы к родительскому узлу

Пример:

Р (проект) Модули (М1, М2, М3, М4). В модуле M1 будут подмодули (M1S1, M1S2, M1S3), а под подмодулем 1 (M1S1) может быть много подмодулей (M1S1S1, M1S1S2, M1S1S3) и т. Д.

Я сделал этот код, используя Recursion и TTreeNode, но я чувствую, что проблема связана с условием.

procedure TForm2.BitBtn1Click(Sender: TObject); 

begin 
lGlblProjID := 1; 
lGlblProjName := 'Project'; 
    ADOConnectionListner.Connected := true; 
    try 
    if ADOConnectionListner.Connected then 
    begin 

      RootNode := TreeView2.Items.Add(nil, lGlblProjName); 
      getSubChild(lGlblProjID, RootNode); 

    end; 
    except 
     on E: Exception do 
     begin 
     ShowMessage('Exception Class = ' + E.ClassName); 
     end; 
end; 
end; 

procedure TForm2.getSubChild(var Pid: Integer; var SubRoot: TTreeNode); 
var 
    lcount, I, lcurrentID: Integer; 
    lcurrentName: String; 
    lModuleNode: TTreeNode; 

begin 
    // ShowMessage(IntToStr(Pid)+ ' '+SubRoot.Text); 

    ADOQuery1.SQL.Clear; 
    ADOQuery1.SQL.Add('SELECT * FROM treetab Where parent_id =:value1'); 
    ADOQuery1.Parameters.ParamByName('value1').Value := Pid; 
    ADOQuery1.Active := true; 
    lcount := ADOQuery1.RecordCount; 

    for I := 0 to lcount - 1 do 
    begin 
    lcurrentID := ADOQuery1.FieldByName('id').AsInteger; 
    lcurrentName := ADOQuery1.FieldByName('name').AsString; 
    ShowMessage(' id ' + IntToStr(lcurrentID) + ' dd ' + lcurrentName); // print valu of i 

    if ((lcurrentID <> 0)and (SubRoot.Text <> '')) then  //or 
    begin 
     lModuleNode := TreeView1.Items.AddChild(SubRoot, lcurrentName); 
     getSubChild(lcurrentID, lModuleNode); 
    end else // if 
    // lcurrentID = 0 

ShowMessage('end reached'); 

// TreeView1.Items.AddChild(SubRoot, ADOQuery1.FieldByName('name').AsString); 


ADOQuery1.Next; 
    //********* 
    end; 

end; 

enter image description here

Я хочу, чтобы получить все вложенные модули для конкретного проекта, как и в данном случае проект только с ID = 1.

+0

Что «оператор условия» вы говорите, у вас возникли проблемы с, и что ваше беспокойство по поводу того, что нельзя? – MartynA

+0

рассмотреть в рамках подвида есть еще одна запись сказать S1 тогда, так как его тогда последний лист возврата SQL ноль и дерево строится половина только P1 -SP -ssp -s1 и затем дерево ломается. – user3036212

ответ

1

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

Что-то вроде (непроверенные):

procedure GetSubChild() 
type 
    TTempRecord = record 
    id: integer; 
    name: string; 
    end; 

    TTempArray = array of TTempRecord; 
var 
    lcount, I, lcurrentID: Integer; 
    lcurrentName: String; 
    lModuleNode: TTreeNode; 
    recs: TTempArray 
begin 
    // ... 
    // query the db 
    // ... 
    lcount := ADOQuery1.RecordCount; 

    SetLength(recs, lcount); 
    for i := 0 to lcount-1 do 
    begin 
    recs[i].id := ADOQuery1.FieldByName('id').AsInteger; 
    recs[i].name := ADOQuery1.FieldByName('name').AsString; 
    ADOQuery1.Next; 
    end; 

    for i := 0 to lcount-1 do 
    begin 
    lcurrentID := recs[i].id; 
    lcurrentname := recs[i].name; 
    // ... 
    // add to treeview 
    // call recursively GetSubChild() 
    // ... 
    end; 
end; 
+0

Поскольку вы упомянули код, который не тестировался. Я тестировал и работает нормально. Благодарю. – user3036212

+0

@user Рад я мог помочь! –