Meine bisherigen Erkenntnisse...
Zusätzlich zu PRISM, Unity, WPF und MVVM verwenden wir auch das Entity Framework und das Xceed-Datenraster. Das Speicherprofil wurde mit dotTrace erstellt.
Ich habe schließlich die IDisposable auf einer Basisklasse für meine Ansichtsmodelle implementiert, wobei die Dispose(bool)-Methode als virtual deklariert wird, um den Unterklassen die Möglichkeit zu geben, auch aufzuräumen. Da jedes Ansichtsmodell in unserer Anwendung einen Kindcontainer von Unity erhält, entsorgen wir diesen ebenfalls, um sicherzustellen, dass das ObjectContext von EF aus dem Geltungsbereich gelangt. Dies war unsere Hauptquelle für Speicherlecks.
Das Ansichtsmodell wird innerhalb einer expliziten CloseView(UserControl)-Methode auf einer Basiskontrollerklasse entsorgt. Es sucht nach einem IDisposable im DataContext der Ansicht und ruft Dispose darauf auf.
Das Xceed-Datenraster scheint einen großen Anteil an den Lecks zu verursachen, insbesondere in lang laufenden Ansichten. Jede Ansicht, die die ItemSource des Datenrasters durch Zuweisen einer neuen Sammlung aktualisiert, sollte Clear() auf der vorhandenen Sammlung aufrufen, bevor sie die neue Zuordnung vornimmt.
Seien Sie vorsichtig mit dem Entity Framework und vermeiden Sie lange laufende Objektkontexte. Es ist sehr unflexibel, wenn es um große Sammlungen geht, auch wenn Sie die Sammlung entfernt haben. Wenn das Tracking eingeschaltet ist, behält es eine Referenz zu jedem Element in der Sammlung bei, selbst wenn Sie nicht mehr an sie hängen.
Wenn Sie das Element nicht aktualisieren müssen, rufen Sie es mit MergeOption.NoTracking ab, insbesondere in langlaufenden Ansichten, die an Sammlungen binden.
Vermeiden Sie Ansichten mit langer Lebensdauer, halten Sie nicht an ihnen fest, wenn sie nicht sichtbar sind. Dies wird Ihnen besonders Kopfschmerzen bereiten, wenn sie ihre Daten in regelmäßigen Abständen aktualisieren, wenn sie sichtbar sind.
Wenn Sie CellContentTemplates auf der Xceed-Spalte verwenden, verwenden Sie keine dynamischen Ressourcen, da die Ressource eine Referenz auf die Zelle enthält, die ihrerseits die gesamte Ansicht am Leben erhält.
Wenn Sie CellEditor auf der Xceed-Spalte verwenden und die Ressource in einem externen Ressourcenwörterbuch gespeichert ist, fügen Sie x:Shared="False" zur Ressource hinzu, die den CellEditor enthält. Dadurch wird sichergestellt, dass Sie jedes Mal eine frische Kopie erhalten, wobei die alte ordnungsgemäß entfernt wird.
Seien Sie vorsichtig beim Binden des DelegateCommand an Elemente innerhalb des Xceed-Datenrasters. Wenn Sie beispielsweise einen Löschbutton in der Zeile haben, der an einen Befehl bindet, stellen Sie sicher, dass Sie die Sammlung, die die ItemsSource enthält, löschen, bevor Sie die Ansicht schließen. Wenn Sie die Sammlung aktualisieren, müssen Sie auch den Befehl neu initialisieren, da der Befehl eine Referenz zu jeder Zeile behält.