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]
undListe.Add(new TreeViewItem(parent))
- Wenn die aktuelle Ebene < Listenanzahl, dann
parent = Liste[aktuelle_Ebene - 1]
undListe[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.
- Wenn die aktuelle Ebene == Listenanzahl, dann
-
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]); } } }