Mein Problem ist, dass ich einer ListBox in WPF viele Elemente hinzufügen muss. In WinForms würden Sie einfach die Methode BeginUpdate (); verwenden, alles hinzufügen und schließlich die Methode EndUpdate (); verwenden.
Also, wie würde ich die Zeichnung in einer WPF-Listbox anhalten, bis jedes Element hinzugefügt wurde, und dann alles auf einmal zeichnen?
Es hört sich so an, als würden Sie die Elemente programmatisch einzeln zu Ihrer Listbox hinzufügen. Ein besserer Ansatz wäre, die Elemente zu speichern, die in einem Modell angezeigt werden sollen, und das Modell an den Datenkontext der Listbox zu binden. Dadurch kann WPF die Rendering-Aktualisierungen übernehmen.
Wenn Sie der Frage Snippets Ihres XAML und Codes hinzufügen (um uns zu zeigen, was Sie gerade tun), können wir möglicherweise eine bessere Antwort liefern.
BEARBEITEN: Ein sehr einfaches Beispiel wurde hinzugefügt.
Hier ist ein Beispiel, das ein Ansichtsmodell an das Hauptfenster (die Ansicht) bindet und dann deklariert das XAML, dass die Daten der ListBox an die Eigenschaft Numbers des Ansichtsmodells gebunden sind.
MainViewModel.cs
%Vor%MainWindow.xaml
%Vor%MainWindow.xaml.cs
%Vor%Wenn Sie gerade mit WPF beginnen, kann Windows Presentation Foundation Unleashed empfohlen werden von Adam Nathan. Es ist ein großartiges Buch und es ist in Farbe zu booten. Andere Bücher danach zu lesen, ist wie nach Visual Studio in den Editor zurückzukehren.
Weitere Informationen zu diesem Model-View-ViewModel finden Sie in Josh Smiths Advanced MVVM Buch.
Verwenden Sie den Dispatcher ordnungsgemäß.
Sie müssen Ihrer ListBox (oder ihrer Datenquelle) Dinge aus dem Dispatcher-Thread hinzufügen, sonst wird die Benutzeroberfläche explodieren. Wenn Sie dies tun, befinden Sie sich entweder bereits in einer Methode für diesen Thread oder (hoffentlich eher) in einem Hintergrundthread und verwenden Dispatcher.BeginInvoke
, um das Element hinzuzufügen.
Wenn Sie das Update auf den Dispatcher übertragen, verwenden Sie Dispatcherpriority.Normal
als Priorität. Der Dispatcher hat eine Warteschlange mit Arbeitselementen und Ihre Normal
-Elemente werden (möglicherweise überraschend) hoch in diese Warteschlange eingefügt.
Das Codebeispiel, das WPF ausführt, um eine Datenbindung zu aktualisieren, wenn sich die zugrunde liegenden Daten geändert haben, wird bei DispatcherPriority.DataBind
ausgeführt, was niedriger ist als Normal
. Das bedeutet, dass die Datenbindung in der Regel erst dann aktualisiert wird, wenn alle Ihre Elemente hinzugefügt wurden (oder wenn Ihre Elemente viel Zeit zum Hinzufügen benötigen, kann dies passieren, wenn der Dispatcher zwischen dem Hinzufügen von Elementen inaktiv ist).
Das Code-Bit, das Ihre Kontrolle tatsächlich ausgibt (z. B. wenn seine Bindung eine Aktualisierung signalisiert), läuft bei DispatcherPriority.Render
und hat sogar eine niedrigere Priorität als die Bindung. Das bedeutet, dass das Steuerelement nur gerendert wird, wenn dem Dispatcher keine Bindungen mehr zum Aktualisieren zur Verfügung stehen, was wiederum nur dann erfolgt, wenn der Dispatcher keine Element-Adds mehr verarbeiten kann.
Wenn das merkwürdig klingt, denken Sie daran, dass jede Ebene (update - binding - render) eine metaphorische Flagge auf der darunter liegenden Ebene setzt - Sie erhalten keine zehn Bindings und dann zehn Renderings. Wenn deine Items schnell sind, bekommst du alle deine Adds gefolgt von einem Bind und einem Render - was perfekt ist.
Grundsätzlich gilt: Wenn Sie den Dispatcher wie vorgesehen verwenden, müssen Sie sich keine Sorgen machen. Es scheint "falsch" zu sein, dem Dispatcher eine relativ niedrige Priorität zu geben, aber eigentlich ist es sehr clever: -)
Da Sie mit großen Listen arbeiten, sollten Sie sich die WPF-UI-Virtualisierung ansehen. Hier ist eine gute Reihe von Blogposts dazu:
Normalerweise würden Sie Elemente in die Sammlung aufnehmen und diese Sammlung mit einem Listbox-Steuerelement verknüpfen. Das Listenfeld sollte, wenn es richtig gemacht wird, keine Elemente aktualisieren, die hinzugefügt werden und nicht sichtbar sind.