Hallo zusammen, ich möchte mit C# und .net 2.0 einen Treeview ausgeben, der aufgeklappt werden kann. Die Daten die ich darin darstelle bekomme ich zyklisch als Liste aus einem anderen (fremden) Modul. D.h. ich muss den Treeview jedesmal von Grund auf neu aufbauen. Wenn der Benutzer jetzt einen Node selektiert und mehrere Nodes aufgeklappt hat, ich dann den Treeview aber neuzeichne (d.h. Treeview löschen und neue Nodes hinzufüge), dann sind alle Nodes zugeklappt und der SelectedNode ist auch nicht mehr ausgewählt. Frage: Wie merkt man sich am besten welche Nodes aufgeklappt waren? Ich suche hier noch eine geniale Idee. Eine Möglichkeit ist natürlich über alle Nodes manuell(!!) zu schleifen (eine Liste ALLER TreeNodes gibt es ja nicht) um deren IsExpanded-Eigenschaft abzufragen und das zugehörige .Tag abzuspeichern, um anschliessend über das Tag und diese Liste die neu gezeichneten Nodes wieder aufzuklappen. Das ist aber sehr umständlich und codeintensiv, zumal der Treeview bis zu 5 Ebenen tief ausgibt. Wie löst ihr das Problem? Danke und Gruß, Martin.
Bin jetzt nicht in dieser Bibliothek "drin"... aber gibts fuer das Auf- und zuklappen sowie Selektieren denn keinen Event, an den man einen Handler haengen kann der den Status zwischenspeichert?
Hi Martin, wo ist das Problem? Du kannst abfragen, welches der selektierte Knoten ist, ob ein Knoten aufgeklappt ist. Ggf. mußt Du an den Knoten einen Verweis hängen, welcher Deiner Datensätze mit welchem Knoten verbunden ist (TreeNode.Tag Property). Mit diesen Informationen (alter TreeView und neu erhaltene Daten) ist es möglich, im Hintergrund einen neuen TreeView aufzubauen. Unabhängig davon würde ich ein eigenständiges Datenmodell führen (im Hintergrund, OHNE TreeView), das bei strukturellen Änderungen des Trees ein Event auslöst, das den TreeView anpasst. In diesem Datenmodell kannst Du alle relevanten Informationen halten. Gruß Markus
> Mit diesen Informationen (alter TreeView und neu erhaltene Daten) ist es > möglich, im Hintergrund einen neuen TreeView aufzubauen. Mache ich ja alles bereits genau so. Allerdings erscheint es mir relativ umständlich zu ermitteln, welcher Node denn jetzt aufgeklappt ist, weil über jede Ebene separat iteriert werden muss. Und ich an der Tag-Eigenschaft nicht immer den gleichen Datentyp dranhängen habe (das ist je nach Ebene unterschiedlich). > Unabhängig davon würde ich ein eigenständiges Datenmodell führen (im > Hintergrund, OHNE TreeView), das bei strukturellen Änderungen des Trees > ein Event auslöst, das den TreeView anpasst. In diesem Datenmodell > kannst Du alle relevanten Informationen halten. Ein eigenständige Datenmodell liegt ja bereits vor (das was ich zyklisch übergeben bekomme). Du meinst aber wohl, dass noch ein weiteres angelegt werden soll, das nur für die Treeview-Darstellung existiert? Ok, dann könnte ich durch Vergleiche zwischen meinem Datenmodell und dem gelieferten Modell feststellen, welche Daten sich geändert haben und daraufhin meine Nodes aktualisieren/hinzufügen/entfernen, aber nicht den gesamten Treeview löschen und wieder von Grund auf neu aufbauen. Dann entfiele das Problem mit dem SelectedNode und den ExpandedNodes... Habe ich das so im Prinzip richtig verstanden? Eventgesteuert kann ich das leider nicht machen(?), da ich ja nur eine vollständige fertige Liste bekomme und beim "Erzeuger" der Liste keine Events auslösen möchte, um die Verstrickung der Programmteile nicht unnötig zu erhöhen. Danke
Martin Altheim wrote: >> Mit diesen Informationen (alter TreeView und neu erhaltene Daten) ist es >> möglich, im Hintergrund einen neuen TreeView aufzubauen. > Mache ich ja alles bereits genau so. Allerdings erscheint es mir relativ > umständlich zu ermitteln, welcher Node denn jetzt aufgeklappt ist, weil > über jede Ebene separat iteriert werden muss. Ja, so ist das nun mal, wenn man eine bereits in Anzeige befindliche Datenstruktur austauscht. > Ok, dann könnte ich durch Vergleiche zwischen meinem Datenmodell und dem > gelieferten Modell feststellen, welche Daten sich geändert haben und > daraufhin meine Nodes aktualisieren/hinzufügen/entfernen, aber nicht den > gesamten Treeview löschen und wieder von Grund auf neu aufbauen. Dann > entfiele das Problem mit dem SelectedNode und den ExpandedNodes... > > Habe ich das so im Prinzip richtig verstanden? Yep. Meistens geh ich diesen Weg. > Eventgesteuert kann ich das leider nicht machen(?), da ich ja nur eine > vollständige fertige Liste bekomme und beim "Erzeuger" der Liste keine > Events auslösen möchte, um die Verstrickung der Programmteile nicht > unnötig zu erhöhen. Eine andere Möglichkeit ist es natürlich, wenn du dir selbst nochmal einen Baum aufbaust, in dem du die angelieferten Daten mit anzeigespezischen Attributen verknüpfst. Dann kannst du wieder auf Events gehen und in deinem erweitertem Baum die entsprechenden Markierungen anbringen. Aber am Abgleich und der Übernahme dieser Attribute in den neu angelieferten Baum führt auch dann kein Weg vorbei.
>Mache ich ja alles bereits genau so. Allerdings erscheint es mir relativ >umständlich zu ermitteln, welcher Node denn jetzt aufgeklappt ist, weil >über jede Ebene separat iteriert werden muss. Und ich an der >Tag-Eigenschaft nicht immer den gleichen Datentyp dranhängen habe (das >ist je nach Ebene unterschiedlich). Ein Baum ist eine rekursive Datenstruktur. Es ist vergleichsweise einfach, rekursive Software darauf loszulassen. Um das Problem der "unterschiedlichen" Datentypen zu erschlagen, gibt es Klassen, Interfaces und/oder Ableitungshierarchien. >Ein eigenständige Datenmodell liegt ja bereits vor (das was ich zyklisch >übergeben bekomme). Du meinst aber wohl, dass noch ein weiteres angelegt >werden soll, das nur für die Treeview-Darstellung existiert? Ja, so ähnlich. Wie Karl heinz Buchegger schreibt, verbietet Dir niemand, im Hintergrund ein Datenmodell zu führen, das ebenfalls eine Baumstruktur hat. Dieses Datenmodell ist unabhängig vom TreeView, der TreeView seinerseits hängt aber direkt vom Datenmodell ab. >Eventgesteuert kann ich das leider nicht machen(?), da ich ja nur eine >vollständige fertige Liste bekomme und beim "Erzeuger" der Liste keine >Events auslösen möchte, um die Verstrickung der Programmteile nicht >unnötig zu erhöhen. Die Events löst Dein Datenmodell aus, wenn es sich ändert. Das mußt Du natürlich selbst implementieren. In .NET verwendet man hierzu Delegates. Beispiele hierfür findest Du im Netz zuhauf. Konsumiert werden die Events des Datenmodells vom (Tree)View, der sich dann entsprechend aktualisieren kann. Man erreicht dadurch eine Entkoppelung von Datenmodell und Datenvisualisierung. Das kann man auch anders machen (z.B. den View vom Modell aus direkt referenzieren), hat dann aber eine Abhängigkeit des Modells vom View, die i.d.R. recht störend ist. Gruß Markus
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.