Mis hallazgos hasta ahora ...
Además de PRISM, Unidad, MVVM WPF y también estamos utilizando Entity Framework y la red de datos Xceed. La creación de perfiles de memoria se realizó con dotTrace.
Terminé implementando IDisposable en una clase base para mis modelos de vista con el método Dispose (bool) que se declara virtual, lo que permite a las subclases la posibilidad de limpiar también. Como cada modelo de vista en nuestra aplicación obtiene un contenedor hijo de Unity, lo desechamos también, en nuestro caso esto asegura que el ObjectContext de EF se salió del alcance. Esta fue nuestra principal fuente de pérdidas de memoria.
El modelo de vista está dispuesto dentro de un método explícito CloseView (UserControl) en una clase de controlador base. Busca un IDisposable en el DataContext de la vista y llama a Dispose on it.
La cuadrícula de datos Xceed parece estar causando una buena parte de las fugas, especialmente en vistas de larga ejecución. Cualquier vista que actualice el ItemSource de la cuadrícula de datos asignando una nueva colección debería llamar a Clear() en la colección existente antes de asignar la nueva.
Tenga cuidado con Entity Framework y evite cualquier contexto de objetos de larga ejecución. Es muy implacable cuando se trata de colecciones grandes, aunque hayas eliminado la colección si el seguimiento está activado, se mantendrá una referencia a cada elemento de la colección, aunque ya no estés pendiente de ellos.
Si no necesita actualizar la entidad, recupérela con MergeOption.NoTracking, especialmente en vistas de larga duración que enlazan a colecciones.
Evite las vistas de larga duración, no las sostenga dentro de una región cuando no son visibles, esto le causará dolor especialmente si actualizan sus datos a intervalos regulares cuando son visibles.
Al usar CellContentTemplates en la Columna Xceed, no use recursos dinámicos ya que el recurso mantendrá una referencia a la celda, que a su vez mantendrá viva la vista completa.
Al usar CellEditor en la Columna Xceed y el recurso se almacena en un diccionario de recursos externo, agregue x: Shared = "False" al recurso que contiene el CellEditor, una vez más el recurso tendrá una referencia a la celda, usando x : Shared = "False" le asegura que obtendrá una copia nueva cada vez, y la anterior se eliminará correctamente.
Tenga cuidado al vincular DelegateCommand a elementos dentro de la cuadrícula de datos Exceed, si tiene un caso como un botón Eliminar en la fila que se une a un comando, asegúrese de borrar la colección que contiene ItemsSource antes de cerrar la vista . Si está actualizando la colección, también necesita reiniciar el comando, así como el comando mantendrá una referencia a cada fila.
LOL, este es un agujero profundo que he estado cavando aquí;) Tenía curiosidad sobre cómo se conecta su comportamiento adjunto en el UserControl, he estado buscando alguna manera de detectar cuándo se va a terminar la vista. Descargar parece ser la opción obvia, pero no es de mucha ayuda, ya que se activará cada vez que la vista se vuelva inactiva –
Ah, es personalizado.Siempre que una vista deba cerrarse llamará a un método en un conjunto de comandos de aplicación que tenemos. Cerrar vista (vista de objeto). Verifico con la tienda detrás de la propiedad adjunta para ver si esa vista o cualquiera de sus vistas secundarias están registradas para tener manejadores cercanos. Si es así, llamo al método que registraron. La única magia aquí es el uso de las clases LogicalTreeHelper y VisualTreeHelper para localizar vistas secundarias. http://msdn.microsoft.com/en-us/library/system.windows.media.visualtreehelper.aspx –
Intentamos descargar también, por cierto. En algunos casos, eso estaba bien ... detendríamos los temporizadores, que básicamente eran solo datos refrescantes, y no había ninguna razón para actualizarlo si la vista no era visible (como si estuviera en pestañas o algo así), pero a veces solo necesito un temporizador que nunca se detenga a menos que la vista se mate y este cierre explícito fue lo mejor que se nos ocurrió. –