2012-06-10 82 views
10

上週我剛開始使用mvvm light開發我的全新Windows 8應用程序。我熟悉mvvmlight WP7導航。我怎樣才能在Windows 8中實現相同的任何人可以提出一個更好的方法來實現在Windows 8中的相同。我找到了一個解決方案,我們在VM中重寫onnavigated事件並處理導航到其他頁面。但我認爲這種方法已經過時了。任何人請指導我正確的實施。提前致謝。通過ViewModel在Windows 8中使用MVVMLight進行頁面導航

+0

請您分享您的解決方案,你怎麼在VM overrided的OnNavigatedTo? –

回答

15

我知道這不是您可能正在尋找的確切答案,但這可能會給您一些探索的想法。

在我的情況下,我沒有使用MVVMLight - 但我自己的簡單MVVM實現。我使用BindableBase類(它隨默認VS 2012 RC模板一起提供)用於屬性通知。我想,你可以使用MVVMLight爲你提供一些基礎設施,你可以用下面的東西來補充。

對於導航,我定義,看起來像一個接口:

,並按如下實現它:

using System; 
using System.Collections.Generic; 
using System.Threading.Tasks; 
using Windows.UI.Xaml.Controls; 

public class NavigationService : INavigationService 
{ 
    private readonly Frame _frame; 

    public NavigationService(Frame frame) 
    { 
     _frame = frame; 
     _frame.Navigated += OnFrameNavigated; 
    } 

    private void OnFrameNavigated(object sender, Windows.UI.Xaml.Navigation.NavigationEventArgs e) 
    { 
     var view = e.Content as IView; 
     if (view == null) 
      return; 

     var navMsg = new NavigationMessage() 
     { 
      Sender = this, 
      NewView = view, 
      Parameter = e.Parameter, 
      NavigationMode = (int)e.NavigationMode 
     }; 

     EventManager.Current.Publish(navMsg); 

     //Anything that the parent needs to be notified should happen in of after this method 
     var viewModel = view.ViewModel; 
     if (viewModel != null) 
      viewModel.Initialise(e.Parameter); 
    } 

    public void Navigate(Type pageType) 
    { 
     DisposePreviousView(); 
     _frame.Navigate(pageType); 
    } 

    public void Navigate(Type pageType, object parameter) 
    { 
     DisposePreviousView(); 
     _frame.Navigate(pageType, parameter); 
    } 

    private void DisposePreviousView() 
    { 
     var currentView = this.CurrentView; 
     var currentViewDisposable = currentView as IDisposable; 
     if (currentViewDisposable != null) 
     { 
      currentViewDisposable.Dispose(); 
      currentViewDisposable = null; 
     } //view model is disposed in the view implementation 
    } 

    public void EnsureNavigated(Type pageType, object parameter) 
    { 
     var currentView = this.CurrentView; 
     if (currentView == null || currentView.GetType() != pageType) 
     { 
      Navigate(pageType, parameter); 
     } 
    } 

    public IView CurrentView 
    { 
     get { return _frame.Content as IView; } 
    } 


    public bool CanGoBack 
    { 
     get { return _frame != null && _frame.CanGoBack; } 
    } 

    public void GoBack() 
    { 
     // Use the navigation frame to return to the previous page 
     if (_frame != null && _frame.CanGoBack) _frame.GoBack(); 
    } 

    public bool CanGoForward 
    { 
     get { return _frame != null && _frame.CanGoForward; } 
    } 

    public void GoForward() 
    { 
     // Use the navigation frame to return to the previous page 
     if (_frame != null && _frame.CanGoForward) _frame.GoForward(); 
    } 

} 

IVIEW:

public interface IView : IDisposable 
{ 
    IViewModel ViewModel { get; } 
    void Refresh(); 
} 

IViewModel:

public interface IViewModel : INotifyPropertyChanged, IDisposable 
{ 
    void Initialise(object parameter); 
    string ViewTitle { get; } 
    void Refresh(); 
} 

最後,在XAML頁面,定義一個Frame元素:

<Frame x:Name="ContentFrame" /> 

,並在頁面的代碼隱藏:(這在我看來,只有醜陋的部分 - 但它希望不是太糟糕):

var _navigationService = new NavigationService(this.ContentFrame); 

您現在可以通過_navigationService到視圖模型。在我的情況下,我創建在頁面的代碼隱藏viewmodel:

public HomePage() 
{ 
    this.InitializeComponent(); 

    var _navigationService = NavigationService.GetFor(this.ContentFrame); 

    DataContext = new HomePageViewModel(_navigationService); 

} 

希望這會有所幫助。

+0

+1 - 我喜歡這種方法。對於「醜陋的部分」,您可以使用DI容器,因此您無需將該服務傳遞給視圖代碼隱藏中的視圖模型。 – EkoostikMartin

+0

MVVMLight的最新版本有一個SimpleIoc,它可以通過幾行代碼將它置於盒子外面。 –

相關問題