MVVM Light: como cancelar o registro do Messenger
Adoro o Messenger do MVVM Light e sua flexibilidade, no entanto, estou com vazamentos de memória quando esqueço de cancelar o registro explícito dos destinatários (no Silverlight 4
A causa é explicadaAqu, mas estou bem com isso, pois acredito que é uma boa prática cancelar o registro explícito dos destinatários de qualquer maneira, em vez de confiar no uso de referências fracas do Mensageiro. O problema é que é mais fácil falar do que faze
ViewModels são fáceis: você geralmente tem controle total sobre o ciclo de vida e pode simplesmenteCleanup()
quando não forem mais necessário
Views, por outro lado, são mais complicados porque são instanciados e destruídos via DataTemplates. Por ex. você pode pensar em umItemsControl
comMyView
como DataTemplate, vinculado a umObservableCollection<MyViewModel>
. OMyView
s controles @ são criados / coletados pelo mecanismo de ligação e você não tem uma boa maneira de chamar manualmente Cleanup (
Tenho uma solução em mente, mas gostaria de saber se é um padrão decente ou se existem alternativas melhores. A idéia é enviar uma mensagem específica do ViewModel para informar ao (s) View (s) associado (s) a descartar:
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);
}
}
Então, quando você chama Cleanup () em um viewModel, todos os modos de exibição que o usam como DataContext também executam seu Cleanup () loca
O que você acha? Estou perdendo algo óbvio?