[英]MVVM Light: how to unregister Messenger
我喜歡MVVM Light的Messenger及其靈活性,但是當我忘記明確取消注冊收件人時(在Silverlight 4中),我遇到了內存泄漏。
原因在這里解釋,但我很好,因為我認為明確取消注冊收件人是一個好習慣,而不是依賴於Messenger使用弱引用。 問題是說起來容易做起來難。
ViewModel很簡單:你通常可以完全控制它們的生命周期,只需要不再需要它們就可以Cleanup()
它們。
另一方面, 視圖更加棘手,因為它們是通過DataTemplates實例化和銷毀的。 對於前者 您可以將帶有MyView
的ItemsControl
視為DataTemplate,綁定到ObservableCollection<MyViewModel>
。 MyView
控件由綁定引擎創建/收集,您無法在它們上手動調用Cleanup()。
我有一個解決方案,但想知道它是否是一個體面的模式或有更好的選擇。 我們的想法是從ViewModel發送一條特定的消息,告訴相關的View處理:
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);
}
}
因此,當您在viewModel上調用Cleanup()時,所有使用它作為DataContext的視圖也將執行其本地Cleanup()。
你怎么看? 我錯過了一些明顯的東西嗎
ViewModelLocator類有助於為視圖模型保留集中存儲。 您可以使用此類來幫助管理新版本並清理舊版本。 我總是通過定位器從視圖中引用我的viewmodel,所以我總是有可以運行的代碼來管理這些東西。 你可以試試。
同樣,我使用Cleanup方法調用Messenger.Unregister(this)
,它清除來自該對象的messenger的所有引用。 你必須每次都調用.Cleanup(),但這就是生活:)
我沒有使用MVVM Light(雖然我聽過很棒的東西)但是如果你想要一個使用WeakReferences的Messenger實現,請查看這里包含的Messenger http://mvvmfoundation.codeplex.com/ 。
MVVM Light Messenger正在使用WeakAction(WeakReference)。 因此您無需顯式取消注冊。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.