Hoher Speicherbedarf und lange Ladezeiten beim Laden einer ListView

  • WPF

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von PadreSperanza.

    Hoher Speicherbedarf und lange Ladezeiten beim Laden einer ListView

    Hallo Leute, ich bin es mal wieder mit neuen Problemen.

    ich habe eine ListView. Die fülle ich mit Daten (es ist ein Telefonbuch und hat daher sehr viele Einträge ~50.000). Wenn ich nun den Tab öffne, in dem sich das Telefonbuch befindet, bleibt das Programm stehen und lädt erstmal fröhlich Daten und nutzt auch viel RAM. Nach etwa 20 Sekunden ist die ListView geladen und die Daten werden angezeigt. Aber das Programm verhält sich äußerst träge. Das heißt einen anderen Eintrag auswählen braucht Zeit. Ich hatte erst das Binding im Verdacht, dass mir die Selection der ListView auf eine Detail-Ansicht gibt. Habe die Bindings gelöscht. Aber das Problem bleibt erhalten.

    Ich habe der ListView lediglich ein DataTemplate gegeben, das einen TextBlock enthält mit drei Runs, sodass ich Nachnamen, Komma und Vornamen anzeige in der View.

    An sich also nichts spektakuläres.

    Und bevor jemand an den 50k Einträgen meckert:

    In meiner Vorversion, die ausschließlich mit CodeBehind geschrieben ist benutze ich exakt die gleiche Liste und statt ListView eine Listbox und füge bei jeder suche alle Einträge manuell hinzu. Da habe ich, wenn ich alle Einträge auf einmal hinzufüge etwa 2 Sekunden "freeze". Der RAM Verbrauch bei der alten Version steigt um etwa 100 MB, was ich für die Datenmenge auch als plausibel empfinde. Bei der neuen Version habe ich nun aber das Problem, dass das Programm mit etwa 60 MB im RAM steht und wenn ich die ListView aktiv fülle, der RAM Bedarf auf bis zu 800 MB steigt. Fülle ich die Collection mit den Daten ohne sie an die View und damit die ListView zu binden, steigt der RAM Bereich auch nur etwa um 100 MB. Also muss da irgendwas sein, das ich falsch mache.

    hat da jemand Erfahrung mit?

    Und falls ihr da ein Projekt braucht, oder euch das anschauen müsst / möchtet... muss ich das erst aufbereiten und DummyWerte erzeugen. Diese dort befindlichen Daten sind von der Arbeit und damit kann ich die nicht einfach weitergeben (Datenschutz etc. ). Das kann ich aber erst frühestens morgen nachliefern. Aber vielleicht habt ihr sowas ja schon mal gesehen oder habt eine Vermutung.

    EDIT: Ich habe auch schon versucht, mittels lazyLoading in der Collection mehrere NotifyChanged Meldungen zu ignorieren und das schneller zu machen. Aber hilft auch nichts. Und der Freeze sowie RAM-Auslastung bleiben persistent hoch
    Dateien
    • NLScC_small.7z

      (2,17 MB, 186 mal heruntergeladen, zuletzt: )

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „PadreSperanza“ ()

    Hallo

    PadreSperanza schrieb:

    Ich habe der ListView lediglich ein DataTemplate gegeben

    Ich vermute hier mal den Fehler. Nämlich in einer kleinen (sicher unbeabsichtigten) Halbwahrheit.

    Ich vermute das du nicht nur einfach ein DataTemplate hast sondern sogar einen Style in welchem du das ControlTemplate überschreibst. Ich bin selbst gespannt ob ich recht habe.
    Es kann allerdings auch sein das dein DataTemplate nicht korrekt "berechnet" werden kann denn.......

    Items für eine ListView oder eine ListBox werden virtualisiert. Per Default ist die Virtualisierung bei diesen beiden Controls eingeschaltet. Das sieht man wenn man sich das original ControlTemplate ansieht daran das die Items innerhalb eines ​VirtualizingStackPanel gerendert werden. Das bewirkt das die WPF zwar alle Daten läd (klar, sind ja gebunden) aber das UI nur für die aktuell sichtbaren Elemente gerendert werden.
    Allerdings muss die Platz welchen diese Elemente brauchen berechnet werden können damit unter anderem die Scrollbar korrekt anzeigt (gefakt wenn man so will) wieviele Elemente die Auflistung enthält.
    Kann dies nicht passieren oder das ControlTemplate enthält erst gar kein ​VirtualizingStackPanel werden natürlich alle Elemente aufwendig gerendert, das führt du langer UI Ladezeit welche nicht mal in einen anderen Thread verlagert werden könnte.

    Lange rede kurzer Sinn, wir brauchen den Code oder noch besser ein Beispiel mit Testdaten. Von mir auch einfach nur 10 Datensätze welche einfach einer Schleife so oft erstellt werden bis es langsam wird.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Ja, ich sitze gerade nicht am Arbeitsrechner (nur dort ist das Programm drauf, da ich es nicht mal mit nach Hause nehmen darf). Deshalb wird es erst morgen was, das zu übermitteln.

    Ich habe darauf in der Tat einen Style definiert. Aber eigentlich nur für den ItemContainerStyle. Aber das könnte natürlich auch einen Effekt haben. Denn die Einträge da drinnen sind ja genau von dem Style beeinflusst :O - Wo du das erwähnst...

    Das heißt, ich müsste bei solchen Sachen generell aufpassen, dass ich auch innerhalb eines Styles - wenn ich damit arbeite - VirtuallizingStackPanels verwende .... oh man :D

    Dass es das Virtualizing als solches gibt, wusste ich bereits. Da habe ich mich damals schon beim alten Programm bereits drüber geärgert, dass meine ListBox das nicht kann, weil ich sie manuell befüllt... (mit ein Grund, warum ich auf binding und MVVM umsteigen möchte).

    Ich lade den BeispielCode in einem "gekürtzen Projekt" mit TestDaten hoch - aber wird leider erst morgen was. Aber schon mal vielen Dank. :)

    Padre.

    PS: Das nächste Bier geht auf mir ;)
    so, ich habe nun das Projekt mal angehangen - als ganzes und habe eine DummyDatei erstellt. Die ist ebenfalls beigefügt. Ob noch Abhängigkeiten enthalten sind, die bei euch zu Fehlern führen können, weil ihr Dateien oder Ordner nicht besitzt, ist recht unwahrscheinlich, da ich sie eigtl am Anfang prüfe. Aber es wäre durchaus möglich.

    Es geht hierbei um folgende Stellen:

    Im MainWindow der Bereich Phonebook. Man kommt hin, indem man bei dem Programm bei den Tabs auf das über dem Zahnrad klickt. Dort ist die Listview im XAML eingetragen.
    Die Logik befindet sich in Viewmodel -> PhonbookViewModel. ACHTUNG: Hier am besten die Funktion LoadData() erst einmal auskommentieren, wenn man es sich im Designer anschauen möchte, da sonst auch der Designer abschmiert und versucht, alle Daten zu laden.

    Das Problem bleibt: Egal ob manuell oder aus der Datei gelesen, es dauert ewig und der RAM müllt voll. Die reaktionszeiten des Programms sind dann jenseits von gut und böse. Damit konnte ich die Datenquelle ausschließen und auch das Laden der Daten in Roh-Form. Es muss also etwas mit der Anzeige der Daten, der ListView oder beidem zu tun haben, wenn ich das richtig sehe. Aber vielleicht fällt euch da ja mehr zu ein.


    Als Hinweis noch vorweg: Das Programm erstellt Ordner und Dateien unter %appdata"/NLScC. Damit ihr sie danach löschen könnt, falls ihr das Programm runterschmeißen möchtet.

    Und ansonsten: Habt bitte Nachsicht mit mir. Wie gesagt, das ist alles eigenständig angeeignet. Wenn es also besser zu machen geht, oder übersichtlicher: Gerne her mit den Hinweisen, aber verurteilt mich deshalb bitte nicht. Programmiere erst seit 1,5 Jahren

    Und leider bin ich mit C# unterwegs. Das alles in VB zu übersetzen, wäre möglich, aber ein größerer Aufwand, den ich gerade nicht leisten kann. Aber vielleicht könnt ihr den Code ja doch verstehen - oder fragt nach :)


    Vielen Dank
    Gruß Pascal
    :)
    Dateien
    • NLSCC2.7z

      (836,67 kB, 186 mal heruntergeladen, zuletzt: )
    Hallo

    Ich bin das mal durchgegangen, war dann doch etwas mehr "sucherei" da du ja sehr viele Styles und Templates da reingepackt hast. Ich nehme an die hast du dir so zusammengesucht und da lag dann auch der Fehler, bei vielen Beispielen wird hald nicht auf alles geachtet.

    PadreSperanza schrieb:

    Gerne her mit den Hinweisen, aber verurteilt mich deshalb bitte nicht.

    Du solltest alle Teilbereiche (die Tabinhalte) in Usercontrols auslagern. Dein Mainwindow ist der knaller. Eine XAML mit fast 900 Zeilen habe ich ja noch nie gesehen.
    Erstelle ein Usercontrol, copy&Paste vom MainWindow in das UserControl, und dieses dann ins MainWindow. Wenn du Fragen hast kannst du gerne Fragen. glaub mir, dann machts auch weit mehr spaß. So ist das nicht lustig.

    Der Fehler lag im Endeffekt an deinem ControlTemplate des ScrollViewers. Die Virtualisierung eines ItemsControl (ListBox, ListView, usw) funktioniert nur wenn gewisse Voraussetzungen erfüllt sind.
    Hierzu zählt auch der Scrollviewer.

    Ersetze in deiner "ScrollViewer.xaml" die Zeile 151 von:

    XML-Quellcode

    1. ​<ScrollContentPresenter Grid.Column="0"/>


    auf

    XML-Quellcode

    1. ​<ScrollContentPresenter Grid.Column="0" CanContentScroll="{TemplateBinding ScrollViewer.CanContentScroll}"/>


    Habe es nun mit einer Million Einträgen getestet - was mit einem Wimpernschlag erledigt ist.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Okay...

    Also vorweg: Vielen herzlichen Dank!!!!!

    nun zum Eingemachten:
    Ja, ich habe bei einigen Styles erstmal schauen müssen, wie man sie generell überschreibt und meistens dann mittels Blend ein Template erstellt und die wichtigen Punkte herauskopiert. Manche Styles sind durch das Internet inspiriert. Aber geschrieben habe ich sie - bis auf eines - alleine. Ich brauche die Styles leider, da ich schon gerne ein komplettes Design hätte. Und wenn ich nun in dem Grauton unterwegs war, wollte ich gerne auch den Scrollbalken in grau und auch die Buttons... und na ja... man findet irgendwie immer noch etwas, das dann wieder mehr ins Design passen muss... Wie gesagt. So viel Ahnung wie du habe ich leider (noch) nicht. Deshalb seid ihr mir hier immer eine sehr große Hilfe, gerade wenn es so merkwürdig ist wie hier.

    Das mit den UserControls werde ich machen. Es war im alten Projekt (alles CodeBehind) auch bereits der Fall. Aber wie in der letzten Frage bereits durchgegangen und von dir beantwortet erwähnt, dachte ich, man dürfe für MVVM die UserControls nicht so einsetzen. Aber das werde ich definitv nachholen und mich sogleich daran machen (wenn die Arbeitslast das erlaubt). Wie ich das generell übertrage, weiß ich im Grunde. Aber sollte ich Fragen haben, werde ich gerne darauf zurückkommen. :)

    Ja, nachdem ich die Zeile geändert habe, ist es schnell und flink und auch für den Designer kein Problem mehr. Doch nun kommt bei mir das große Fragezeichen:

    Was genau bewirkt ​CanContentScroll="{TemplateBinding ScrollViewer.CanContentScroll}" denn nun? Ich habe das im Template ja nirgends drin, an was genau binde ich das hier denn dann eigtl?

    Und warum genau hatte das nun diesen Effekt, den ich wahrgenommen hatte? Ich verstehe den Zusammenhang leider nicht.
    Denn eigentlich sorgt CanContentScroll doch dafür, dass ich entweder pixelhaft oder elementhaft scrolle. Oder bin ich hier wieder falsch?

    Gruß
    Pascal

    PadreSperanza schrieb:

    Ich habe das im Template ja nirgends drin, an was genau binde ich das hier denn dann eigtl?

    Ich versuchs mal zu erklären, bin da nicht so gut.

    TemplateBinding bewirkt (wie du es des öfteren in deinen Styles hast) das in der Hirarchie nach oben das Binding weitergegeben wird. In deinem Fall befindet sich das ja in deinem ScrollViewer.
    Ein Itemscontrol (wie z.b. die Listview, die erbt ja von einem Itemscontrol) besitzt einen Scrollviewer. Das erkennt man sehr gut daran das hier MS ein AttachedProperty für den ScrollViewer implementiert hast.
    Das ist der Grund warum man im ListView das Property ​ScrollViewer.VerticalScrollBarVisibility="Hidden" oder eben ​ScrollViewer.CanContentScroll="True" setzen kann.
    zum Thema AttachedProperty habe ich auch ein Kapitel erstellt.

    OK, weiter. Intern versucht die WPF (wenn alles korrekt ist vom Template her) nun das ganze zu Virtualisieren indem es die Einträge innerhalb eines VirtualizingStackPanels rendert. Dafür muss die oben genannte Eigenschaft des ScrollViewers entsprechend gesetzt werden was die WPF auch macht und zwar mittels AttachedProperty, gibst du nun aber diesen Wert NICHT weiter an den eigentlichen ScrollViewer weil du die Eigenschaft nicht mittels "TemplateBinding" darauf bindest dann kommt der Wert auch nie beim ScrollViewer an und die WPF kann eben nicht virtualisieren.

    Ich hoffe ich konnte es etwas erklären.


    PadreSperanza schrieb:

    Aber geschrieben habe ich sie - bis auf eines - alleine.

    Respekt. Sieht finde ich garnicht so doof aus, oft etwas klein, aber sonst finde ich es gut.

    PadreSperanza schrieb:

    Ich brauche die Styles leider, da ich schon gerne ein komplettes Design hätte.

    Alles gut, soll ja so sein. Ist ja eine der Stärken der WPF.

    PadreSperanza schrieb:

    So viel Ahnung wie du habe ich leider (noch) nicht.

    Dafür ist das Forum ja da. Nur Mut. Es gibt auch keine Dummen Fragen, bloß dumme Antworten. Und niemand ist perfekt, ich lerne jeden einzelnen Tag dazu und von gut bin ich auch weit entfernt.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Nofear23m schrieb:

    Respekt. Sieht finde ich garnicht so doof aus, oft etwas klein, aber sonst finde ich es gut.

    Ja, genau dafür gibt es in den Settings die Optionen, dass man die Sachen vergrößern und nach belieben anpassen kann wie FontSize, Buttongröße, und auch die Applications können angepasst werden. Das an die Bedürfnisse der Nutzer anzupassen, war mir dann auch wichtig, da jeder ja ein eigenes Empfinden hat und auch Bedürfnisse.

    Nur auch hier gibt es wohl noch Verbesserung: Ich müsste vielleicht die Farben nicht immer direkt ansprechen mit Background="LightGray", sondern sollte die Farben vielleicht als Ressource definieren. Sollte ich später mal was ändern wollen, muss ich nicht in jeden einzelnen Style


    Nofear23m schrieb:

    OK, weiter. Intern versucht die WPF (wenn alles korrekt ist vom Template her) nun das ganze zu Virtualisieren indem es die Einträge innerhalb eines VirtualizingStackPanels rendert

    Okay, das heißt, wenn ich das richtig verstanden habe: dadurch, dass bei mir diese Angabe fehlt, bleibt diese Property irgendwo im Nirvana hängen => WPF kommt nicht ganz klar => Virtualization wird deaktiviert => Alle Elemente (~50k) werden nun aufgefordert nach dem entsprechenden Template gerendert zu werden, was also bedeutet, dass ~50k TextBoxen auch gerendert werden => hohe RAM-Last.

    Fazit: Auch das Nutzen von Styles hat so seine Tücken.

    Hab vielen Dank!

    Aber eine Frage hätte ich doch noch (möchte es ja verstehen):
    Wie genau bist du nun vorgegangen, um herauszufinden, dass der Fehler genau hier lag? Ich finde WPF schwierig zu debuggen. Ich meine, du wirst dir den Codebereich, den es betrifft, angeschaut haben. Aber wie kommt man darauf, dass es nun am ScrollContentPresenter liegt?

    PadreSperanza schrieb:

    Wie genau bist du nun vorgegangen, um herauszufinden, dass der Fehler genau hier lag?

    Also erstmal habe ich alle Style herausgenommen und nach und nach in der App.xaml auskommentiert.

    Alles klappte, gut nun nach dem ausschlussprinzip, da ich ja nun wusste das es an einem Style/Template liegen muss.
    Als ich wusste es liegt an dem ScrollViewer habe ich mir den LiveTree angesehen.



    Da sieht man nun auch welche Eigenschaften überschrieben wurden und welche wie aktuell gesetzt sind und in deinem Fall wieviele Elemente (Textboxen) wirklich im VisualTree erzeugt wurden.
    Dann wars schnell gefunden.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Sooo ich mal wieder :D

    Ich hatte bemerkt, dass mein ProgramManager ebenfalls höhere RAM Auslastung und Ladezeiten hat, wenn ich versuche, diesen aufzurufen. Teilweise braucht es bis zu 8 Sekunden, um die Daten zu laden und anzuzeigen - das Programm friert dabei ein. Ich hatte auch erst daran gedacht, dass es hier ebenfalls an einem Style liegen könnte. Das konnte ich aber ausschließen, da ich eine abgespeckte Variante gemacht habe, in der nur noch der ProgramManager vorhanden war und dann habe ich alle Styles entfernt. Ich habe Test-Daten geladen (400 Einträge) und habe sie nach ca. 0,5 - 1 Sekunde angezeigt bekommen. Die Resonanz nach 05 - 1 Sekunde ist für 400 Einträge, bei denen jeweils ein Icon geladen wird, in Ordnung und vertretbar zumal die UI nicht eingefroren ist. Ich habe nach und nach alle Styles wieder zugeschaltet und auch nach dem letzten Style -> 0,5 -1 s (Varianz begründe ich mal mit den CPU-Zeiten, die meiner App dann zugesprochen werden). Also alles tutti...

    Dann habe ich mir überlegt: Was ist dann anders zu dem quasi "release fertigen" Programm. und dann fiel mir etwas auf: Die Testdaten werden hinzugefügt durch einfaches Hinzufügen zur Collection:

    C#-Quellcode

    1. private void LoadTestData()
    2. {
    3. int k = 0;
    4. for (int i = 0; i < 100; i++)
    5. {
    6. _managedApplications.Add(new ManagedApplication(ApplicationType.Application, "Test" + i, @"C:\Users\P16250\Desktop\NLSCC2Test\mappe1.xlsx", k.ToString(), "", "", true));
    7. _managedApplications.Add(new ManagedApplication(ApplicationType.Application, "Test_" + i, @"C:\Programmierung\GSFDAT\gsfdat.cs", k.ToString(), "", "", true));
    8. _managedApplications.Add(new ManagedApplication(ApplicationType.Application, "Test_A" + i, @"C:\Users\P16250\Videos\wildlife.wmv", k.ToString(), "", "", true));
    9. _managedApplications.Add(new ManagedApplication(ApplicationType.Application, "Test_BBA" + i, @"C:\Users\P16250\Desktop\start.bat", k.ToString(), "", "", true));
    10. if (i % 10 == 0) k++;
    11. }
    12. }


    Soweit kein Hexenwerk und eine Resonanz von der oben erwähnten Zeit. Ändere ich in der abgespeckten Version die Initialisierung derart ab, dass ich nicht die Test-Dateien sondern die richtigen Dateien lade. Ergebnis: Ladezeit von 4-9 Sekunden auch in der abgespeckten Version. Das heißt, die Krux liegt nun hier irgendwo begraben, da alles andere ja supi funktioniert. Nun habe ich aber ein kleines Problemchen: Die Initialisierung des ProgramManagers beginnt ja eigentlich schon bei Programm-Start (wenn ich einen Einstiegspunkt setze, dann wird mir das MainWindow auch erst angezeigt, wenn ich da schrittweise durch scrolle). Das Problem mit der Darstellung findet jedoch erst statt, wenn ich den Tab für den ProgramManager öffne und mir das View anzeigen lasse. Das heißt, das Laden meiner Daten kann eigtl auch nicht das Problem sein, da die Daten bei Initialisierung bereits bereitstehen und auch alle 200 Einträge (die ebenfalls nur Test-Einträge sind) sind zumindest in der Collection enthalten. Also muss die Darstellung in Bezug auf diese Daten das Problem sein.
    Ich hole mir diese Collection quasi aus einer Datei und weise dann alle Einträge der Collection meiner Variablen zu, auf welche ich danach die View festlege. Gibt es da nun eine Möglichkeit festzustellen, welche Mechanismen aktiv werden, sobald ich auf den Tab klicke und das View anzeigen lasse, um dann vielleicht zu sehen, was mich hier ausbremst?

    Hier noch kurz der Ausschnitt der Zuweisung der geladenen Daten:

    C#-Quellcode

    1. private void LoadFilesFromDisk()
    2. {
    3. string path = AppSettings.ProgramManagerFilePath;
    4. if (System.IO.File.Exists(path))
    5. {
    6. ManagedAppCollection appColl = new ManagedAppCollection();
    7. appColl = (ManagedAppCollection)Reader.ReadFile(path, appColl,"pmm"); //Hier ist lediglich der Reader, der eine XML-Datei einliest
    8. CopyToCollection(appColl);
    9. LogConsole.Log("PgrogramManager-Files erfolgreich geladen");
    10. }
    11. }
    12. private void CopyToCollection(ManagedAppCollection collection)
    13. {
    14. foreach (ManagedApplication ma in collection)
    15. {
    16. _managedApplications.Add(ma);
    17. }
    18. LogConsole.Log("Konfiguration erfolgreich geladen");
    19. }


    Der Log zeigt mir sodann auch, dass diese Collection schon bei Programm-Start zur Verfügung steht. Das heißt, der eigentlich "ReadFile"-Vorgang ist nicht die Bremse, sondern die Darstellung muss hier ein Problem haben. Ich weiß nur gerade nicht, warum, da die Daten als Testdaten - hardgecoded - dieses Verhalten nicht derart aufweisen
    Hallo

    Schwer zu sagen was genau hier das Problem ist. Hast du denn Bindingfehler in der Ausgabe.
    Bindingfehler können wirklich extrem ausbremsen.

    Sonst ist es nur mit dem Code schwer auszumachen.
    Du redest von einem Tabwechsel - wie ist der Code von diesem Denn (Programmcode und XAML).

    Schwer zu sagen.
    Du kannst durch Logausgaben (inkl. Zeitstempel) recht einfach prüfen wo wirklich das Problem liegt.

    Grüße
    Sascha
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Bindungsfehler bekomme ich keine.

    Der Tab sieht wie folgt aus:

    XML-Quellcode

    1. <!--#region PROGRAMMANAGER-->
    2. <TabItem>
    3. <TabItem.Header>
    4. <Image Width="{Binding TabSize,Converter={StaticResource TabSizeConverter},Source={StaticResource AppSettings}}" Source="images\programmanager\programmanager.png" ToolTip="Programm-Manager"/>
    5. </TabItem.Header>
    6. <view:ProgramManagerView AppWidth="{Binding Source={StaticResource AppSettings}, Path=ManagedAppWidth}"
    7. AppHeight="{Binding Source={StaticResource AppSettings}, Path=ManagedAppHeight}"
    8. ImageAlignment="{Binding Source={StaticResource AppSettings}, Path=ManagedAppImageAlignment}"
    9. ImageSize="{Binding Source={StaticResource AppSettings}, Path=ManagedAppImageSize}"
    10. FontSize="{Binding Source={StaticResource AppSettings}, Path=FontSize}"/>
    11. </TabItem>
    12. <!--#endregion-->


    (btw: macht es Sinn die Source des Images auch als Pack-Uri anzugeben?)

    Ich habe nun mal in den Testdaten auch andere ApplicationTypes mit reingenommen. Aber die Testdaten bleiben performant. Nur habe ich jetzt im Designer eine IOException, da ein Image nicht gefunden werden konnte (was als Fallback gesetzt werden soll). Diese setze ich mit einem Converter. Wenn als Testdaten implementiert, läuft auch alles super und der Fall-Back-Wert der Source wird richtig gesetzt. Also muss ich hier auch nochmal irgendwie nachschauen.

    Schwer zu sagen.Du kannst durch Logausgaben (inkl. Zeitstempel) recht einfach prüfen wo wirklich das Problem liegt.
    Der Erstversuch war ja schon da: Die Logs mit Zeitstempel passieren ja beim Laden der Daten in die Collection. Das geschieht aber noch bevor ich in den Tab wechseln kann. Das einzige, was mir nun einfällt wäre im Converter nochmal einen Log zu schreiben und zu schauen, was hier wie passiert.
    Aber wenn ich das richtig sehe habe ich keine Möglichkeit mir irgendwelchen Code anzuschauen, sobald ich auf den Tab klicke (abgesehen vom Converter)?



    EDIT: Ich habe nun im Converter mal Zeitstempel reingeballert. Jedesmal wenn er eine Access-Datenbank gefunden hat (und versuchte, das Icon zu finden) hab es etwa 2-3 Sekunden Pause vor dem nächsten Eintrag. Habe die Einträge entfernt, neu geladen -> zack alles da. Also scheint es ein Problem zu sein, auf eine AccessDatenbank zu zugreifen wie ich das versuche.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „PadreSperanza“ ()

    Hallo

    Innerhalb eines Converters derartige abfrsgen zu tätigen ist imho immer schlecht. Solche Daten sollten im RAM liegen. Mach dir für die relevanten Daten eine Singleton Klasse und pack diese bei Programmstart rein. Hier kannst du im erstfall sehr einfach einen Splashscreen anzeigen falls es länger dauert.

    Aber den Fehler haste schon mal. Gratuliere.
    If _work = worktype.hard Then Me.Drink(Coffee)
    Seht euch auch meine Tutorialreihe <WPF Lernen/> an oder abonniert meinen YouTube Kanal.

    ## Bitte markiere einen Thread als "Erledigt" wenn deine Frage beantwortet wurde. ##

    Die Abfrage habe ich ja nur reingepackt, um erstmal überhaupt drauf zugreifen zu können. Aber die relevanten Daten selbst sind ja bereits bei Programmstart vorhanden. Soweit war auch alles gut. Also hat tatsächlich der Windows-API-Call, den ich ausführe, um das Icon aus der Datei zu ziehen einen signifikanten Einfluss auf die Anzeige selbst.

    Und damit das nicht missverstanden wird, im Converter liegen im Augenblick lediglich der Application Type und der Pfad (Internet-Pfad/lokaler Pfad) der Datei vor (und nun zusätzlich auch ein Console-Log). Das Herausziehen des Icons mit dem API-Call und alle weiteren Dinge geschehen nicht mehr im Converter, sondern sind in der ManagedApplication Datei selbst verankert, wo ich sie auch brauche. Der Converter gibt lediglich zwei Dinge zurück: Den Typ und eine BitmapSource, die aus dem Pfad generiert wird (wobei bei ApplicationType.Website (Chrome, IE, Firefox) jeweils das Bild als Ressource übergeben wird. Wird ApplicationType.Application zurückgegeben, sucht die Klasse eine eigene BitmapSource anhand der API-Funktion