MVVM Light:如何取消注册Messenger

Fra*_*ori 42 c# silverlight mvvm silverlight-4.0 mvvm-light

我喜欢MVVM Light的Messenger及其灵活性,但是当我忘记明确取消注册收件人时(在Silverlight 4中),我遇到了内存泄漏.

原因在这里解释,但我很好,因为我认为明确取消注册收件人是一个好习惯,而不是依赖于Messenger使用弱引用.问题是说起来容易做起来难.

  • ViewModel很简单:您通常可以完全控制它们的生命周期,并且可以Cleanup()在不再需要它们时使用它们.

  • 另一方面,视图更加棘手,因为它们是通过DataTemplates实例化和销毁的.对于前者 你可以把ItemsControlwith MyView和DataTemplate 想象成一个ObservableCollection<MyViewModel>.该MyView控件创建/绑定引擎收集的,你有没有什么好办法对他们手动调用清理().

我有一个解决方案,但想知道它是否是一个体面的模式或有更好的选择.我们的想法是从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);
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,当您在viewModel上调用Cleanup()时,所有使用它作为DataContext的视图也将执行其本地Cleanup().

你怎么看?我错过了一些明显的东西吗

Cam*_*ute 6

ViewModelLocator类有助于为视图模型保留集中存储.您可以使用此类来帮助管理新版本并清理旧版本.我总是通过定位器从视图中引用我的viewmodel,所以我总是有可以运行的代码来管理这些东西.你可以试试.

同样,我使用Cleanup方法调用Messenger.Unregister(this),它清除来自该对象的信使的所有引用.你必须每次都调用.Cleanup(),但这就是生活:)


Bra*_*der 1

我没有使用过 MVVM Light(尽管我听说过很棒的事情),但如果您想要使用 Wea​​kReferences 的 Messenger 实现,请查看此处包含的 Messenger http://mvvmfoundation.codeplex.com/

  • MVVM light 使用弱引用 (3认同)