mvvm light Messenger.Default.Register在View代码后面?

时间:2011-09-26 20:20:14

标签: c# design-patterns architecture mvvm mvvm-light

Mix11 上展示的 BookShelf 解决方案 John Papa 对我来说听起来有些奇怪...... 它使用 MVVM 模式和 MVVM Light工具包 ......一切都很棒。 唯一我无法理解是这样的: 在视图的代码隐藏中注册了几条消息,这里是代码:

public partial class BookView : Page
{
    public BookView()
    {
        InitializeComponent();
        //btnEdit.SetBinding(Button.IsEnabledProperty, new Binding("User.IsAuthenticated") { Source = Application.Current.Resources["WebContext"] });
        Title = ApplicationStrings.HomePageTitle;
        RegisterMessages();
    }

    private void RegisterMessages()
    {
        Messenger.Default.Register<LaunchEditBookMessage>(this, OnLaunchEditBook);
        Messenger.Default.Register<SavedBookDialogMessage>(this, OnSaveBookDialogMessageReceived);
    }

    private void OnLaunchEditBook(LaunchEditBookMessage msg)
    {
        var editBook = new EditBookWindow();
        editBook.Show();
    }

    private void OnSaveBookDialogMessageReceived(SavedBookDialogMessage msg)
    {
        MessageBox.Show(msg.Content, msg.Caption, msg.Button);
    }
//...

这是一个业务应用程序,如果您从该页面切换到另一个页面然后再返回该页面,该页面再次实例化并继续注册以查找导致这些内容的消息多次开火 ......

怎么来它在代码隐藏中而不是在ViewModels中订阅这些消息?这与UI线程有关吗? **这是正确的实施吗?

如果用户导航到其他网页,您将如何取消注册这些消息?

编辑:经过修改的代码

XAML

<sdk:Page Loaded="Page_Loaded" Unloaded="Page_Unloaded">

代码背后

private void Page_Loaded(object sender, RoutedEventArgs e)
    {
        RegisterMessages();
    }

    private void Page_Unloaded(object sender, RoutedEventArgs e)
    {
        Messenger.Default.Unregister(this);
    }

1 个答案:

答案 0 :(得分:4)

是的,这看起来像他的例子中的一个错误。他可能不希望页面在应用程序中多次实例化。您可以使用Messenger.Default.Unregister方法挂接Unloaded事件来解决此问题(您可以考虑将注册表移至Loaded

我明白为什么他把事件放在View中。他正在打开一个新窗口并调用MessageBox.Show(),因为它们与View紧密耦合,他将它们保存在View中。我个人仍然不喜欢这个解决方案...

其他MVVM框架可以更好地解决这个问题,例如Caliburn。它有很多辅助类可以从ViewModel中执行类似View的事情。 Caliburn可以100%消除代码隐藏中的任何东西,但它有一个非常大的学习曲线。