TreeView



  • Hallo in die Runde.

    Ich lese aus einer Datenbank die Tabelle für die Erstellung eines Trees ein. Im Moment so:

    if (frmTree->objQuery->FieldByName("parent")->AsString == "") {
    	frmTree->objTree->Items->Add(NULL, frmTree->objQuery->FieldByName("Bezeichnung")->AsString);
    }
    else {
    	Node1 = frmTree->objTree->Items->Item[frmTree->objQuery->FieldByName("parent")->AsInteger - 1];
    	frmTree->objTree->Items->AddChild(Node1, frmTree->objQuery->FieldByName("Bezeichnung")->AsString);
    }
    
    

    Ich will es umstellen und das Feld Parent löschen und nur mit der Ebene arbeiten. Aber ich scheitere an der Logik das umzusetzen.

    Sort	Parent	Ebene				
    1		0	Root1			
    2	1	1		Child1		
    3	2	2			Child1_1	
    4	2	2			Child1_2	
    5	2	2			Child1_3	
    6	1	1		Child2		
    7	6	2			Child2_1	
    8	6	2			Child2_2	
    9	1	1		Child3		
    10	9	2			Child3_1	
    11	9	2			Child3_2	
    12	11	3				Child3_2_1
    13	11	3				Child3_2_2
    14	11	3				Child3_2_3
    15	9	2			Child3_3	
    16	1	1		Child4		
    17	16	2			Child4_1	
    18	16	2			Child4_2	
    19	16	2			Child4_3	
    20		0	Root2			
    
    


  • Nochmal zum Hintergrund

    Die Struktur des Trees wird in einem StringGrid erfasst. Daher wäre es einfach die Struktur zu speichern, die Ebene = die Spaltenposition.

    Ich versuch grad das Grid rückwärts zu lesen und so das Parent eines jeden Nodes zu ermitteln. Theoretisch können Node Texte mehrfach vorkommen.

    Es gibt sicherlich bessere Ansätze, bin da offen und dankbar für 🙂



  • Du benötigst dafür eine Liste, welche die höheren TreeViewItem-Elemente (Parents) speichert:

    • Wenn die aktuelle Ebene == Listenanzahl, dann parent = Liste[Liste.Count - 1] und Liste.Add(new TreeViewItem(parent))
    • Wenn die aktuelle Ebene < Listenanzahl, dann parent = Liste[aktuelle_Ebene - 1] und Liste[aktuelle_Ebene] = new TreeViewItem(parent)
    • aktuelle Ebene > Listenanzahl sollte nicht vorkommen (Exception?)

    Für den Root brauchst du evtl. eine Sonderbehandlung.

    PS: Aus dem Kopf geschrieben, können also evtl. noch Fehler drin sein.



  • Hallo MichiFeld,
    so ganz verstanden habe ich dein Problem nicht, habe es auch nur kurz überflogen.

    Ich verwende TreeView sehr häufig und hatte noch nie Probleme. Allerdings füge ich die Knoten nicht mit AddChild() ein sondern mit AddObject(). Bei AddObject() kann ein Pointer auf ein beliebiges Objekt übergeben werden (Struktur, Klasse). Dieses Objekt enthält dann alle zur identifizierung des Knotens benötigten Daten. In den Knoten kann dann über die Eingenschaft "Data" auf das jeweilige Objekt zugegriffen werden.

    Hier sind ein paar Beispiele, vielleicht hilft dir das weiter:
    https://docwiki.embarcadero.com/CodeExamples/Alexandria/en/TreeNodesAddObject_(C%2B%2B)
    https://docwiki.embarcadero.com/CodeExamples/Alexandria/e/index.php?title=Category:C%2B%2B&pagefrom=SysUtilsStrLCat+(C%2B%2B)#mw-pages



  • Ich bin jetzt doch dabei geblieben die Parents in der Datenbank zu speichern.
    Der Anwender kann den Baum in einem StringGrid erfassen und dann erstell ich daraus die Struktur für den Tree und kann meine Daten speichern.

    String sTab[100][2]; // Spalte 1 Bezeichnung, Spalte 2 Parent-Node
    int iRowCount = objGrid->RowCount;
    int iTab = objGrid->RowCount - 1;
    TTreeNode *Node1;
    
    TreeView1->Items->Clear();
    
    // Grid rückwärts durchlaufen
    for (int i = objGrid->RowCount - 1; i > 0; i--) {
    	// Prüfen in welcher Spalte Text steht
    	for (int j = 0; j < objGrid->ColCount; j++) {
    		if (objGrid->Cells[j][i] != "") {
    			sTab[i][0] = objGrid->Cells[j][i];
    			// Erster Root
    			if (j == 0) {
    				sTab[i][1] = "";
    			}
    			else {
    				// Ab Grid Zeile rückwärts
    				for (int k = i - 1; k > 0; k--) {
    					if (objGrid->Cells[j - 1][k] != "" && objGrid->Cells[j][k] == "") {
    						// Parent zuweisen
    						sTab[i][1] = k;
    						break;
    					}
    				}
    			}
    		}
    	}
    }
    
    // Tree aufbauen
    for (int i = 0; i < 100; i++) {
    	if (sTab[i][0] != "") {
    		if (sTab[i][1] == "") {
    			TreeView1->Items->Add(NULL, sTab[i][0]);
    		}
    		else {
    			Node1 = TreeView1->Items->Item[StrToInt(sTab[i][1] - 1)];
    			TreeView1->Items->AddChild(Node1, sTab[i][0]);
    		}
    	}
    }
    
    

Anmelden zum Antworten