mvvm light Messenger.Default.Register在View codebehind中?

Jac*_*ova 5 c# architecture design-patterns mvvm mvvm-light

书架的解决方案约翰爸爸提出了在MIX11有一些听起来有点奇怪,我...它使用MVVM模式和MVVM光工具包 ......一切都很好.唯一不明白的是: 在Views的代码隐藏中它注册了几条消息,这里是代码:

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);
    }
//...
Run Code Online (Sandbox Code Playgroud)

它是一个业务应用程序,如果你从那个页面切换到另一个页面,然后再回到那里,页面再次实例化并继续注册那些导致多次触发的消息...

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

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

编辑:修改后的代码

XAML

<sdk:Page Loaded="Page_Loaded" Unloaded="Page_Unloaded">
Run Code Online (Sandbox Code Playgroud)

代码背后

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

    private void Page_Unloaded(object sender, RoutedEventArgs e)
    {
        Messenger.Default.Unregister(this);
    }
Run Code Online (Sandbox Code Playgroud)

jon*_*ers 4

是的,这在他的示例中看起来像是一个错误。他可能不希望页面在应用程序中多次实例化。有一种方法Messenger.Default.Unregister可以让您挂钩 Unloaded 事件来解决此问题(您Loaded也可以考虑将寄存器移至.

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

其他 MVVM 框架可以更好地解决这个问题,例如Caliburn。它有很多帮助器类可以从 ViewModel 中执行类似 View 的操作。Caliburn 可以 100% 消除代码隐藏中的任何内容,但它有一个相当大的学习曲线。