【问题标题】:NavigationService throws NullReferenceExceptionNavigationService 抛出 NullReferenceException
【发布时间】:2011-05-08 17:27:58
【问题描述】:

使用 MVVM Light,我正在尝试开发一个相当简单的 WP7 应用程序。我在使用导航服务时遇到了问题。我可以导航到一个页面,但是在按下后退按钮后,我无法再次导航到同一页面。 NavigationService 引发 NullReferenceException。

我已经使用 GalaSoft.MvvmLight.Messaging 命名空间中的 Messaging 实现了我的导航。我的所有视图都继承自定制的 PhoneApplicationPage 基类,该基类在“NavigationRequest”上注册了一个侦听器:

public class PhoneApplicationPage : Microsoft.Phone.Controls.PhoneApplicationPage
{
    public PhoneApplicationPage() : base()
    {
        Messenger.Default.Register<Uri>(this, "NavigationRequest", (uri) => NavigationService.Navigate(uri));
    }
}

从我的视图模型中,我将 Uri 发布到此侦听器:

SendNavigationRequestMessage(new Uri("/View/AppSettingsView.xaml", UriKind.Relative));

就像我说的那样,除了在按下后退按钮后进行导航外,这都有效。 为什么会这样,我该如何解决?

有没有更好的方法来使用 MVVM Light 实现导航?

【问题讨论】:

    标签: windows-phone-7 mvvm navigation mvvm-light


    【解决方案1】:

    我也在使用 MVVM Light。我有一个名为 PageConductor 的类,它基于 Microsoft 的 John Papa (Silverlight MVP) 所使用的。这是我使用的 PageConductor 服务

    public class PageConductor : IPageConductor
    {
        protected Frame RootFrame { get; set; }
    
        public PageConductor()
        {
            Messenger.Default.Register<Messages.FrameMessage>(this, OnReceiveFrameMessage);
        }
        public void DisplayError(string origin, Exception e, string details)
        {
            string description = string.Format("Error occured in {0}. {1} {2}", origin, details, e.Message);
            var error = new Model.Error() { Description = description, Title = "Error Occurred" };
            Messenger.Default.Send(new Messages.ErrorMessage() { Error = error });
        }
    
        public void DisplayError(string origin, Exception e)
        {
            DisplayError(origin, e, string.Empty);
        }
        private void OnReceiveFrameMessage(Messages.FrameMessage msg)
        {
            RootFrame = msg.RootFrame;
        }
        private void Go(string path, string sender)
        {
            RootFrame.Navigate(new Uri(path, UriKind.Relative));
        }
        public void GoBack()
        {
            RootFrame.GoBack();
        }
    }
    

    在我的 MainPage.xaml.cs 构造函数中,我有这个,它在我的 PageConductor 服务中创建我的 ContentFrame 的一个实例。:

    Messenger.Default.Send(new Messages.FrameMessage() { RootFrame = ContentFrame });
    

    然后我使用依赖注入将我的 PageConductor 服务实例实例化到我的 MainPage ViewModel 中。这是我的 MainViewModel 类:

    protected Services.IPageConductor PageConductor { get; set; }
        public RelayCommand<string> NavigateCommand { get; set; }
    
        public MainViewModel(Services.IPageConductor pageConductor)
        {
    
            PageConductor = pageConductor;
            RegisterCommands();
        }
        private void RegisterCommands()
        {
            NavigateCommand = new RelayCommand<string>(
                (source) => OnNavigate(source));
    
        }
        private void OnNavigate(string sender)
        {
            PageConductor.GoToView(sender, "main");
        }
    

    请注意我的 PageConductorService 实例作为 MainViewModel 构造方法中的参数。我通过我的 ViewModelLocator 传递这个:

    private readonly TSMVVM.Services.ServiceProviderBase _sp;
    public ViewModelLocator()
    {
        _sp = Services.ServiceProviderBase.Instance;
    CreateMain(_sp);
    }
            #region MainPageViewModel
        public static MainViewModel MainStatic
        {
            get
            {
                Services.ServiceProviderBase SP = Services.ServiceProviderBase.Instance;
                if (_main == null)
                {
                    CreateMain(SP);
                }
    
                return _main;
            }
        }
    
        [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance",
             "CA1822:MarkMembersAsStatic",
             Justification = "This non-static member is needed for data binding purposes.")]
        public MainViewModel Main
        {
            get
            {
                return MainStatic;
            }
        }
    
        public static void ClearMain()
        {
            _main.Cleanup();
            _main = null;
        }
    
        public static void CreateMain(Services.ServiceProviderBase SP)
        {
            if (_main == null)
            {
                _main = new MainViewModel(SP.PageConductor);
            }
        }
        #endregion
    

    为了进一步参考,我的 Messages.FrameMessage 类很简单:

    internal class FrameMessage
    {
        public Frame RootFrame { get; set; }
    }
    

    前进/后退按钮没有问题。

    【讨论】:

    • 非常感谢。过了一段时间,我让你的例子工作了。我现在可以导航了 :-) 非常感谢 Scott!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-05-30
    • 2020-11-17
    • 2016-03-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多