Мне нравится Messenger MVVM Light и его гибкость, однако у меня возникают утечки памяти, когда я забываю явно отменить регистрацию получателей (в Silverlight 4).
Причина объяснена здесь , но я в порядке с этим, так как считаю, что хорошей практикой является явная отмена регистрации получателей в любом случае, вместо того, чтобы полагаться на использование мессенджером слабых ссылок. Проблема в том, что легче сказать, чем сделать.
ViewModels просты: вы обычно имеете полный контроль над их жизненным циклом и можете просто Cleanup()
их, когда они больше не нужны.
С другой стороны, представления сложнее, потому что они создаются и уничтожаются с помощью DataTemplates. Например вы можете представить ItemsControl
с MyView
как DataTemplate, связанный с ObservableCollection<MyViewModel>
. MyView
элементы управления создаются / собираются механизмом привязки, и у вас нет хорошего способа вручную вызвать Cleanup () для них.
Я имею в виду решение, но хотел бы знать, является ли это приличным шаблоном или есть лучшие альтернативы.
Идея состоит в том, чтобы отправить определенное сообщение из ViewModel, чтобы сообщить связанным представлениям удалить:
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);
}
}
Поэтому, когда вы вызываете Cleanup () для viewModel, все представления, которые используют его в качестве DataContext, будут также выполнять локальную очистку ().
Что ты думаешь? Я что-то упускаю из виду?