2011-05-08 61 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