mvvm light Messenger.Default.Register in View codebehind?

本文关键字:View codebehind in Register light Messenger Default mvvm | 更新日期: 2023-09-27 18:09:50

BookShelf解决方案John PapaMix11上展示的东西听起来有点奇怪…它使用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线程有关?这是一个正确的实现吗?

如果用户导航到另一个页面,您将如何注销这些消息?

EDIT: refactoring CODE

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);
    }

mvvm light Messenger.Default.Register in View codebehind?

是的,这看起来像他的例子中的一个bug。他可能不希望页面在应用程序中实例化多次。有一个Messenger.Default.Unregister的方法,你可以钩到一个卸载事件来解决这个问题(你也可以考虑将寄存器移动到Loaded)。

然而,我理解他为什么把事件放在视图中。他正在打开一个新窗口并调用MessageBox.Show(),因为这些与视图紧密耦合,所以他将它们保留在视图中。我个人还是不喜欢这个解决方案……

其他MVVM框架可以更好地解决这个问题,比如Caliburn。它有很多帮助类从你的ViewModel做类似视图的事情。Caliburn可以100%消除代码隐藏中的任何东西,但它有一个相当大的学习曲线。