J'aime le MVVM Light et de son Messager et sa souplesse, cependant je suis en train de vivre des fuites de mémoire quand j'oublie explicitement annuler l'inscription des bénéficiaires (dans Silverlight 4).
La cause en est expliqué ici, mais je suis très bien avec lui que je crois que c'est une bonne pratique explicitement annuler l'inscription des bénéficiaires de toute façon, plutôt que de compter sur le Messager de l'utilisation de références faibles. Le problème est que c'est plus facile à dire qu'à faire.
Viewmodel sont faciles: généralement, vous avez le plein contrôle sur leur cycle de vie et peuvent seulement
Cleanup()
quand ils ne sont plus nécessaires.Points de vue sur l'autre main sont plus difficiles parce qu'ils sont instanciés et détruit par DataTemplates. Pour ex. vous pouvez penser à un
ItemsControl
avecMyView
comme DataTemplate, lié à unObservableCollection<MyViewModel>
. L'MyView
des contrôles sont créés, recueillis par le moteur de liaison et vous n'avez pas de bonne façon de manuellement appel Cleanup() sur eux.
J'ai une solution à l'esprit mais je voudrais savoir si c'est un décent motif ou il y a de meilleures alternatives. L'idée est d'envoyer un message à partir de ce Dernier de dire à la Vue associée(s) à éliminer:
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);
}
}
Ainsi, lorsque vous appelez Cleanup() sur un viewModel tous les points de vue de l'utiliser comme DataContext sera exeute leur local de Nettoyage() ainsi.
Qu'en pensez-vous? Ai-je raté quelque chose d'évident?