TListView::OnChange: Ende der Auswahl behandeln
-
Hallo zusammen,
ich habe folgendes Problem:
Ein Formular enthält zwei ListViews, das linke enthält Verzeichnisse, das rechte die Dateien der im rechten ListView ausgewählten Verzeichnisse. Jedes Mal, wenn im rechten ListView ein Eintrag ausgewählt/abgewählt wird, muss das rechte ListView aktualisiert werden. Wenn im linken ListView ziemlich viele Einträge ausgewählt werden, wird für jeden Eintrag ein OnChange Event ausgelöst, das die Aktualisierung des rechten ListView nach sich zieht. Das ist natürlich ziemlich blöd, da eigentlich eine einzige Aktualisierung ausgereicht hätte, und bei einer Mehrfachauswahl mit 500 Verzeichnissen wird das rechte ListeView 500x neu befüllt, was Ewigkeiten dauert.Als Lösung habe ich im Moment einen TTimer, der alle 50 msec ein Flag überprüft, ob das rechte ListView neu befüllt werden muss. Im Ereignishandler für das linke ListView wird dann lediglich das Flag gesetzt. Funktioniert, ist flott, aber irgendwie unbefriedigend.
Hat da jemand eine bessere Idee?
Gruß,
Doc
-
Hallo
Vermutlich könnte man mit mehr Hintergrundinfos über den Zweck und Einsatz erstmal die eigentliche Abfragefunktion für ListView2 optimieren.
Für diese abstrakte Situation fällt mir erstmal nur dieser Vorschlag ein : Du baust die Trennung der beiden ListViews noch weiter aus. Der OnChange von ListView1 schreibt seine Änderung erstmal nur in eine passende Queue obendrauf.
Für ListView2 integrierst du nun einen Thread, der jeweils auf der anderen Seite der Queue die Änderungen verarbeitet und ListView2 aktualisiert. Das ganze muß natürlich sauber synchronisiert werden.bis bald
akari
-
Hintergrundinfos:
Das linke ListView enthält alle Verzeichnisse einer Suchabfrage, das rechte die Dateien der aktuellen Auswahl. Der Benutzer kann jetzt im linken ListView Verzeichnisse markieren, deren zusammengefasste Dateien im rechten ListView angezeigt werden. Viel mehr gibts da eigentlich nicht zu sagen.
Im Moment ist es so, dass ein Ereignishandler für das OnChange Event des linken ListView das rechte ListView komplett neu aufbaut, da steckt also relativ wenig Intelligenz dahinter.
Das mit dem Thread halte ich für Overkill, ich brauche lediglich die Information, ob sich die Auswahl im linken ListView geändert hat, was sich geändert hat ist egal.Der Pseudocode dazu sieht etwa so aus:
void F::OnChange() { ListViewRight->Clear(); foreach( ListItem Item in ListViewLeft ) { if( Item->Selected ) { foreach( string Name in Item->Files ) { ListViewRight->Items->Add( Name ); } } } }
Wenn jetzt 100 Einträge ausgewählt werden, wird diese Funktion 100x aufgerufen. Die ersten 99 Events interessieren mich aber nicht, da jedes Mal eine vollständige Aktualisierung stattfindet. Die Behandlung des letzten Events reicht also völlig aus.
-
Hallo
Im Moment ist es so, dass ein Ereignishandler für das OnChange Event des linken ListView das rechte ListView komplett neu aufbaut, da steckt also relativ wenig Intelligenz dahinter.
Dann setz da an, und bau eine Intelligenz ein. Ein kompletter Aktualisierung von ListView2 mit Dateien aus 499 Verzeichniss ist doch gar nicht notwendig, nur weil Verzeichnis 500 neu dazukommt. Sondern es müßen doch nur die Dateien aus dem neuen Verzeichnis hinzugefügt werden. Alles was du dann noch beachten mußt, ist das beim Deaktivieren eines Verzeichnises in ListView1 alle Dateien aus ListView2 entfernt werden, die zu dem Verzeichnis gehören. Dazu mußt du zumindestens im Hintergrund zu den Datei-Items in ListView2 nicht nur den Namen der Datei zwischenspeichern, sondern auch das Verzeichnis. Ich empfehle dafür die Verwendung von TListItem::Data, damit kannst du Informationen an ein Item anhängen. Du must dir nur Gedanken über Speicherverwaltung machen, wenn du mehr als ein Integer oder einen Zeiger da reinsteckst.
bis bald
akari
-
Für solche Situationen ist immer ListView::OwnerData einen Blick wert. Meiner Erfahrung nach ist das überhaupt der einzige Weg, das ListView für große Datenmengen benutzbar zu halten.