2016-08-08 17 views
0

Ich habe eine ListView basierte Steuerung. Es ist ein Datei-Explorer. Wenn die Eigenschaft Path festgelegt ist, werden zuerst alle Dateisystemelemente durch eine asynchrone Methode geladen (mithilfe der Win32-API). Dies ist super schnell sogar für eine große Anzahl von Dateien. Wie auch immer, für C: \ Windows \ System32 sehe ich keine Verzögerung. Die Artikel werden dann zu meinem ListView in Chargen von 64 hinzugefügt, nachdem jede 64 Dispatcher.Yield() erwartet wird, um anzuzeigen, was vor dem Abschluss der Operation hinzugefügt wurde. Dies macht das Ganze wieder viel schneller und reaktionsfähiger.ListView blinkt schwarz bei der Größenänderung, wenn eine große Anzahl von Elementen innerhalb

Es gibt jedoch einen nicht sehr schnellen Vorgang: Wenn ich zum ersten Mal ein Icon für eine Datei brauche, muss ich einen Systemaufruf machen. Dieser Aufruf wird in Getter gemacht, es ist schlau, es versucht den Cache zu benutzen, wenn er verfügbar ist.

Das Laden der Ansicht ist ein Blinzeln.

Wenn ich jedoch ein riesiges Verzeichnis (kein Problem, schnell) - und dann Größe oder das Fenster zu maximieren - sehe ich einige schwarze Flash, bevor das Steuerelement die Größe ändert.

Es ist wie zuerst das Fenster ändert die Größe, der zusätzliche Platz ist schwarz lackiert, dann erscheint die größere ListView. Es ist Abendessen nervig und wie verwüstet meine glatte Erfahrung. Gibt es eine Möglichkeit, diesen schwarzen Raum zu vermeiden?

Ich habe versucht, Window Hintergrund weiß, hat nicht geholfen. Ich versuchte, meinen UserControl, der ListView Hintergrund enthält, zu Weiß zu setzen. Keine Freude.

Wenn es nicht viele Elemente in der ListView gibt, gibt es keinen schwarzen Blitz, aber es ist immer noch nicht glatt genug.

Also - wie kann man verhindern, einen schwarzen Hintergrund zu sehen, während das Steuerelement in der Größe geändert wird?

+0

Es ist unmöglich, ohne eine gute [mcve] sicher zu wissen. Aber es klingt, als ob Sie das WPF-Äquivalent ausführen, indem Sie lang laufenden Code im UI-Thread ausführen und 'Application.DoEvents()' in regelmäßigen Abständen aufrufen. Dies ist eine schlechte Idee in Winforms und das WPF-Äquivalent ist auch eine schlechte Idee. Der lange laufende Code sollte in einer Hintergrundaufgabe ausgeführt werden und den UI-Thread regelmäßig benachrichtigen, wenn ein Update durchgeführt werden muss. Es gibt viele Fragen und Antworten zu Stack Overflow, die bereits diese grundlegende Technik ansprechen. Bitte verbessern Sie die Frage, wenn Sie denken, dass Ihr Szenario einzigartig ist und Sie mehr Hilfe benötigen. –

+2

Fügen Sie programmatisch ein 'ListViewItem' für jedes Dateisystemelement hinzu? Wenn ja, erstellen Sie einen ziemlich großen visuellen Baum. Haben Sie versucht, Ihre 'ListView' mit einem MVVM-Ansatz zu binden? Wenn Sie die Objektcontainervirtualisierung aktivieren, verfügen Sie nie über (viele) weitere Elemente, die tatsächlich in das Ansichtsfenster passen, und die Elemente werden jedes Mal wiederverwendet, wenn ein Element nicht mehr angezeigt wird. Die Größenänderung sollte dann ziemlich bissig sein, obwohl Sie möglicherweise ein asynchrones, faules Icon-Laden einrichten müssen, um die Dinge flüssig zu halten. –

+0

@PeterDuniho: Ich benutze alle lange laufenden Code außerhalb UI-Thread - so funktionieren asynchrone Methoden. Meine 'OnPropertyChanged'-Überschreibung ist async markiert und es läuft außerhalb des Benutzeroberflächen-Threads. Ich bin mir nicht sicher, ob ein minimales Beispiel helfen würde, weil es das besprochene Verhalten nicht zeigen kann, und das Einfügen meines vollständigen Codes macht keinen Sinn. In Ordnung, ich werde es auf einfachere Weise testen und ich werde es hier einfügen, wenn das Verhalten beobachtet werden konnte. – Harry

Antwort

0

Wenn jemand Probleme mit der Leistung ListView hat - hier ist etwas sollte dagegen getan werden:

  1. nicht ausführt keine teueren Operationen auf UI-Thread. In meinem Fall war es nicht genau so, aber ähnlich. Der fehlerhafte Code wurde im Elementkonstruktor ausgeblendet. Beim Start wurde versucht, einige Zeichenfolgenkonvertierungen vorzunehmen. Sehr schlechte Idee, alle teuren Operationen wurden zu Gettern verschoben, die die Hälfte des Problems lösten. Der Item-Konstruktor sollte leer sein. Keine Anfangswerte Keine Initialisierung überhaupt. Alle Eigenschaften sollten über Getter gelesen werden. Dies führt dazu, dass 20 solcher Operationen pro Ansicht statt wie 20000 ausgeführt werden, jedoch nur, wenn die UI-Virtualisierung verwendet wird.

  2. Verwenden Sie MVVM-Muster, also fügen Sie keine Elemente direkt hinzu, erstellen Sie eine Elementquelle und fügen Sie Elemente zur Quelle hinzu. Dies würde eine integrierte UI-Virtualisierung ermöglichen, die für eine große Anzahl von Elementen unerlässlich ist. Suchen Sie "UI-Virtualisierung ListView" in Google für weitere Details. Dies hat das Problem definitiv gelöst.

  3. Denken Sie an Datenvirtualisierung, wenn das Füllen der Elementquelle zu langsam ist. In meinem Fall war das unnötig. Wenn wir alle Daten bekommen, ist das relativ günstig - wir sind gut. Wenn nicht, müssen wir nur einen Teil der Daten abrufen, die aktuell angezeigt werden müssen.

  4. Eine einfachere Kontrollschablone könnte die Anwendungsleistung auf einigen mobilen Endgeräten ein wenig steigern.

  5. Wenn Sie nicht verwalteten Code irgendwo in Ihrer Anwendung verwenden, überprüfen Sie es zweimal, ich habe vergessen, DestroyIcon einmal aufzurufen, und es führte zu sehr seltsam, unerwartetes Verhalten. Also entsorg alles wegwerfbare, zerstöre unbenutzte Griffe und ähnliches. Machen Sie dreifach sicher, dass es erledigt ist, ich habe unzählige Stunden damit verschwendet, solche Dinge zu debuggen. Um es klar zu sagen: Unveröffentlichte Ressourcen verursachten keine Leistungsprobleme, es verursachte andere unerwartete Verhaltensweisen wie seltsame Ausnahmen, verschwindene Symbole und ähnliches. Die Probleme schienen jedoch von ListView zu kommen.