mvvmlight galasoft c# silverlight mvvm silverlight-4.0 mvvm-light

c# - galasoft - nuget mvvmlight



MVVM Light: cómo cancelar el registro de Messenger (3)

La clase ViewModelLocator ayuda a mantener una tienda centralizada para sus modelos de vista. Puede usar esta clase para ayudar a administrar nuevas versiones y limpiar las antiguas. Siempre hago referencia a mi viewmodel desde la vista a través del localizador, por lo que siempre tengo el código que puedo ejecutar para administrar estas cosas. Podrías probar eso.

Además, utilizo el método Cleanup para llamar a Messenger.Unregister(this) , que limpia todas las referencias del messenger para ese objeto. Tienes que llamar a .Cleanup () todo el tiempo, pero así es la vida :)

Me encanta el Messenger de MVVM Light y su flexibilidad, sin embargo, tengo pérdidas de memoria cuando olvido anular el registro explícito de los destinatarios (en Silverlight 4).

La causa se explica here , pero estoy de acuerdo, ya que creo que es una buena práctica anular el registro explícito de los destinatarios de todos modos en lugar de confiar en el uso de referencias débiles del Messenger. El problema es que es más fácil decirlo que hacerlo.

  • ViewModels es fácil: por lo general, usted tiene control total sobre su ciclo de vida y solo puede Cleanup() cuando ya no los necesita.

  • Las vistas, por otro lado, son más complicadas porque se crean instancias y se destruyen a través de DataTemplates. Por ej. puede pensar en un ItemsControl con MyView como DataTemplate, ligado a un ObservableCollection<MyViewModel> . Los controles MyView son creados / recopilados por el motor de enlace y no tiene una buena manera de llamar manualmente a Cleanup ().

Tengo una solución en mente pero me gustaría saber si es un patrón decente o si hay mejores alternativas. La idea es enviar un mensaje específico de ViewModel para indicar a la (s) Vista (s) asociada (s) que desechen:

public class MyViewModel : ViewModelBase { ... public override void Cleanup() { // unregisters its own messages, so that we risk no leak Messenger.Default.Unregister<...>(this); // sends a message telling that this ViewModel is being cleaned Messenger.Default.Send(new ViewModelDisposingMessage(this)); base.Cleanup(); } } public class MyView : UserControl, ICleanup { public MyView() { // registers to messages it actually needs Messenger.Default.Register<...>(this, DoSomething); // registers to the ViewModelDisposing message Messenger.Default.Register<ViewModelDisposingMessage>(this, m => { if (m.SenderViewModel == this.DataContext) this.Cleanup(); }); } public void Cleanup() { Messenger.Default.Unregister<...>(this); Messenger.Default.Unregister<ViewModelDisposingMessage>(this); } }

Por lo tanto, cuando llame a Cleanup () en un viewmodel, todas las vistas que lo utilicen como DataContext también eximirán a su limpieza local ().

¿Qué piensas? ¿Me estoy perdiendo algo obvio?


MVVM Light Messenger está utilizando WeakAction (WeakReference). Por lo tanto, no es necesario que elimine el registro de forma explícita.


No he usado MVVM Light (aunque he escuchado cosas buenas), pero si quieres una implementación de Messenger que use WeakReferences, revisa el Messenger incluido aquí http://mvvmfoundation.codeplex.com/ .