【问题标题】:Handling the OnNavigatedFrom / OnNavigatedTo events in the ViewModel处理 ViewModel 中的 OnNavigatedFrom / OnNavigatedTo 事件
【发布时间】:2010-07-27 21:43:00
【问题描述】:

我正在尝试找出一种方法,让我的 ViewModel 在页面导航自或至时处理保存或恢复页面状态。

我尝试的第一件事是向页面添加 EventToCommand 行为,但事件(OnNavigatedFrom 和 OnNavigatedTo)被声明为受保护,并且 EventToCommand 看不到要绑定的事件。

接下来我想我会尝试使用 Messenger 类通过 View 后面的代码中的代码向 ViewModel 传递消息:

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
    Messenger.Default.Send<PhoneApplicationPage>(this);
    base.OnNavigatedFrom(e);
}

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    Messenger.Default.Send<PhoneApplicationPage>(this); 
    base.OnNavigatedTo(e);
}

但这似乎有两个问题,首先是在代码隐藏页面中有此代码。其次,ViewModel 无法区分 OnNavigatedFrom 和 OnNavigatedTo 事件,而无需为 PhoneApplicationPage 对象创建一个包装类(请参阅下面的更新)。

处理这些事件最适合 MVVM-Light 的方式是什么?

更新: 我能够通过发送这样的消息来解决第二个问题:

protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
    Messenger.Default.Send<PhoneApplicationPage>(this,"NavigatedFrom");
    base.OnNavigatedFrom(e);
}

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
    Messenger.Default.Send<PhoneApplicationPage>(this, "NavigatedTo"); 
    base.OnNavigatedTo(e);
}

并像这样注册它们:

Messenger.Default.Register<PhoneApplicationPage>(this, "NavigatedFrom", false, (action) => SaveState(action));
Messenger.Default.Register<PhoneApplicationPage>(this, "NavigatedTo", false, (action) => RestoreState(action));

【问题讨论】:

    标签: windows-phone-7 mvvm-light


    【解决方案1】:

    从后面的代码中执行命令比处理整个消息传递过程要干净得多。毕竟视图知道它的 DataContext 并没有错。

        protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            base.OnNavigatedTo(e);
            viewModel.NavigatedToCommand.Execute(e.Uri);
        }
    
        ProfileViewModel viewModel
        {
            get
            {
                return this.DataContext as ProfileViewModel;
            }
        }
    

    更新:传入 NavigationContext.QueryString 可能更有用,因为它已经解析出参数和值。

    【讨论】:

    • 我不反对 MVVM Light。我只是在考虑它的执行时间。通过 ViewModelLocator 从 VIEW 到 ViewModel
    【解决方案2】:

    抱歉,这个问题迟到了三年。是的,我仍在使用 Silverlight。好的,我想在Page 代码隐藏中这样写:

    // Executes when the user navigates to this page.
    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        this.HandleOnNavigatedTo(e);
    }
    

    我正在使用这样的扩展方法:

    public static void HandleOnNavigatedTo(this Page page, NavigationEventArgs e)
    {
        var vm = page.DataContext as IPageNavigationViewModel;
        if (vm == null) return;
        vm.HandleOnNavigatedTo(e);
    }
    

    扩展方法意味着Page 必须有一个在DataContext 中实现IPageNavigationViewModel 的视图模型。对我来说,这是一个关注点分离的折衷方案,页面只知道域中最通用的数据类型。这是界面:

    using System.Windows.Navigation;
    
    namespace Fox.Silverlight.ViewModels
    {
        /// <summary>
        /// Defines View Model members for frame-navigation pages.
        /// </summary>
        public interface IPageNavigationViewModel
        {
            /// <summary>
            /// Handles the <see cref="Page.OnNavigatedTo"/> method in the View Model.
            /// </summary>
            /// <param name="e">The <see cref="NavigationEventArgs"/> instance containing the event data.</param>
            void HandleOnNavigatedTo(NavigationEventArgs e);
    
            /// <summary>
            /// Handles the <see cref="Page.OnNavigatedFrom"/> method in the View Model.
            /// </summary>
            /// <param name="e">The <see cref="NavigationEventArgs"/> instance containing the event data.</param>
            void HandleOnNavigatedFrom(NavigationEventArgs e);
        }
    }
    

    【讨论】:

      【解决方案3】:

      看起来您已经有了解决问题的方法。我还建议以下内容:

      查看使用mvvm-toolkit中提供的消息值之一,如:

          NotificationMessage<T>
      

      像这样:

          Messenger.Default.Send<NotificationMessage<PhoneApplicationPage>>(
      new NotificationMessage<PhoneApplicationPage>(this, "Message"));
      

      【讨论】:

        【解决方案4】:

        我认为 Ryan 的意思是,您使用 PhoneApplicationPage 作为正在发送的消息,而不是实际消息。

        你正在这样做:

        Messenger.Default.Send<PhoneApplicationPage>(this);
        

        它正在发送PhoneApplicationPage 类型的消息。您可能不需要将整个 PhoneApplicationPage 作为消息发送。

        您可以为 NavigatingTo / NavigatingFrom 制作一些消息,即。

        Messenger.Default.Send<NavigatingToMessage>(new NavigatingToMessage());
        

        等等

        我确信有一百万种更好的方法可以做到这一点,我只是按照你的设置方式进行。就个人而言,我的 ViewModelBase 类具有 NavigatingTo/NavigatingFrom 方法,我覆盖了视图中的相应方法并将它们发送到我的 ViewModel。

        【讨论】:

          【解决方案5】:

          我使用问题中的更新答案制作了一个示例:

          MainViewModel.xaml.cs:

          public class MainViewModel : ViewModelBase
          {
              public MainViewModel()
              {
                  Messenger.Default.Register<PhoneApplicationPage>(this, "NavigatedTo", false, ExecuteNavigatedTo);
              }
          
              // action contains everything you want.
              private void ExecuteNavigatedTo(Page page)
              {
                  // example
                  bool b = page.NavigationContext.QueryString.ContainsKey("id");
              }
          }
          

          MainViewModel.xaml.cs:

          protected override void OnNavigatedTo(NavigationEventArgs e)
          {
              Messenger.Default.Send<PhoneApplicationPage>(this, "NavigatedTo");
              base.OnNavigatedTo(e);
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2013-08-05
            • 2013-09-25
            • 2010-12-26
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-09-18
            • 2014-01-23
            相关资源
            最近更新 更多