Langsame Baumansicht in C #

8

Ich habe eine Legacy-Anwendung, die in C # geschrieben ist und eine sehr komplexe Baumansicht mit 10 bis 20 tausend Elementen anzeigt.

In der Vergangenheit stieß ich auf ein ähnliches Problem (aber in C ++), dass ich mit der OWNERDATA-Fähigkeit, die von der Win32-API angeboten wird, gelöst habe.

Gibt es einen ähnlichen Mechanismus in C #?

EDIT: Der Plan ist, sowohl die Erstellungszeit als auch die Browserzeit zu optimieren. Die Methode, die über die Win32-API verfügbar ist, ist in beiden Fällen hervorragend, da sie die Initialisierungszeit auf Null reduziert und die Anzahl der Anforderungen für Elemente auf nur die jeweils sichtbaren beschränkt ist. Joshl: Wir machen eigentlich genau das, was Sie bereits vorgeschlagen haben, aber wir brauchen noch mehr Effizienz.

    
Fabien Hure 23.09.2008, 13:49
quelle

6 Antworten

6

Ich glaube nicht, dass das .NET TreeView unterstützt, was Sie wollen, obwohl diese Art von Modell von .NET DataGridView unterstützt wird (siehe DataGridView VirtualMode Eigenschaft). Mit der TreeView können Sie Ihre eigenen Knoten zeichnen, aber Sie können sie nicht aus einem virtuellen Speicher auffüllen.

Wenn möglich, sollten Sie die Verwendung eines DataGridView für Ihre Anwendung in Betracht ziehen. Wenn nicht, kann die manuelle Verwaltung der Knoten (wie oben erwähnt) funktionieren, wenn Sie einige Probleme bei der korrekten Aktualisierung des Bildschirms bei der Knotenerweiterung vermeiden können. Darüber hinaus sollten Sie sich einige der Drittanbieter ansehen, z. B. diesen (Devilements SandGrid) , das (die Betonung auf Macht) könnte Ihre gewünschte Arbeitsweise unterstützen.

HINWEIS: Das SandGrid wird ab Ende Juli 2013 nicht von Divelements unterstützt.

    
Ken Wootton 23.09.2008, 14:08
quelle
19

Eine Technik zur Verbesserung der Leistung besteht darin, TreeNodes zu laden, wenn der Benutzer die Baumansicht erweitert. Normalerweise benötigt ein Benutzer nicht 20.000 Knoten gleichzeitig auf seinem Bildschirm geöffnet. Laden Sie nur die Ebene, die der Benutzer sehen muss, zusammen mit allen untergeordneten Informationen, die Sie benötigen, um dem Benutzer die Affordances richtig anzuzeigen (Symbol erweitern, wenn Kinder vorhanden sind, zählt, Symbole usw.). Während der Benutzer Knoten erweitert, laden Sie Kinder gerade rechtzeitig.

Hilfreicher Hinweis von Keith: Mit dem winforms TreeView müssen Sie mindestens einen Kind-Knoten haben oder es wird nicht die Erweiterung [+] angezeigt, aber Sie behandeln das TreeNodeExpanded-Ereignis, um diesen Dummy-Knoten zu entfernen und die Kinder zu füllen.

    
JoshL 23.09.2008 13:53
quelle
8

In unserer WinForm-Hauptanwendung haben wir eine Baumansicht, die alle in einem Bild geladen ist:

  • BeginUpdate ()
  • Laden Sie 20.000 Knoten
  • EndUpdate ()

und bis jetzt ist die Leistung noch nett. Es ist tatsächlich eine der wenigen Komponenten, die wir nicht durch Dritte ersetzen.

Die TreeView-Leistung wird nach meiner Erfahrung langsam, wenn Sie Knoten laden (auf einmal oder auf Anforderung), ohne Begin / EndUpdate () aufzurufen, insbesondere wenn Ihre Knoten sortiert sind, aber wenn Sie Begin / EndUpdate () aufrufen richtig, Sie sollten nicht wirklich Leistungsprobleme im Zusammenhang mit der Komponente selbst erhalten.

    
Filini 23.09.2008 15:04
quelle
7

HINWEIS: Diese Antwort wird durch eine Bearbeitung durch den Fragesteller ungültig gemacht, indem er sagt, dass er diese Art von Dingen schon tut, aber ich entschied mich, sie für zukünftige Referenzen von anderen zu diesem Thema zu veröffentlichen.

Wenn ich in der Vergangenheit ähnliche Dinge gemacht habe, habe ich mich eher für den naiven Lazy-Loading-Stil entschieden.

  • Verwenden Sie die Eigenschaft TreeNode.Tag , um eine Referenz zu speichern, mit der Sie die untergeordneten Elemente suchen können
  • Verwenden Sie das TreeView.BeforeExpand -Ereignis, um die untergeordneten Knoten
  • aufzufüllen
  • Verwenden Sie optional das Ereignis TreeView.AfterCollapse , um sie zu entfernen.
  • Um die Felder [+] / [-] erscheinen zu lassen, habe ich am besten einen Singleton-Dummy TreeNode gefunden, der allen unbestückten Knoten als untergeordnetes Element hinzugefügt wird und auf seine Existenz überprüft wird vor dem Auffüllen mit BeforeExpand .
Alex Lyman 23.09.2008 14:27
quelle
4

Es gibt eine Möglichkeit, die TreeView viel besser zu machen, nämlich alle Unterknoten zu erstellen und sie zusammen zu haken und dann die Knoten zur TreeView hinzuzufügen. Wenn es um die grafische Leistung geht, über die wir sprechen.

%Vor%

Laden Sie sie andernfalls Knoten für Knoten mit OnTreeNodeExpanded .

    
Seb Nilsson 23.09.2008 14:18
quelle
1

Für große Daten in Windows C # -Programmierung, sei es in WPF oder WinForms, habe ich traditionell Knoten dynamisch hinzugefügt. Ich lade die ursprüngliche Baumstamm + Kinder + Enkel tief. Wenn ein Knoten erweitert wird, lade ich die Baumknoten, die die Enkel des expandierenden Knotens repräsentieren würden, falls vorhanden.

Dieses Muster funktioniert auch gut beim Datenabruf. Wenn Sie wirklich Daten aus einer Quelle von Tausenden oder Millionen von Datensätzen laden, möchten Sie diese wahrscheinlich nicht alle im Voraus laden. Kein Benutzer möchte auf das Laden warten, und es gibt keinen Grund, Daten zu laden, die möglicherweise nie angezeigt werden.

Normalerweise habe ich die Knotendaten der Enkel oder Urenkelkinder nach Bedarf in einen Hintergrundthread geladen, dann diese Daten zurück zum UI-Thread gemarshallt und die Knoten erstellt und hinzugefügt. Dies lässt die Benutzeroberfläche ansprechend. Sie können Baumknoten optisch verzieren, um anzuzeigen, dass sie immer noch geladen werden, falls ein Benutzer Ihre IO in den Datenspeicher bringt.

    
Jason Jackson 23.09.2008 14:49
quelle