2011-05-08 60 views
2

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

我已经使用GalaSoft.MvvmLight.Messaging命名空间中的消息传递实现了我的导航。我所有的观点从registrers的“NavigationRequest”侦听器定制的PhoneApplicationPage基类继承:

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导航?

回答

0

我也使用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服务:

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

然后我使用依赖创建我的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; } 
} 

我已经与前进/后退按钮没有问题。

+0

非常感谢。过了一段时间,我得到了你的例子工作。我现在可以导航:-)非常感谢斯科特! – Vern 2011-05-09 08:36:30

+0

很高兴我能帮助队友。 – 2011-05-09 18:09:24