Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Page navigation through ViewModel using MVVMLight in windows 8

I just started developing my brand new windows 8 application last week using mvvm light.I am familiar with mvvmlight WP7 navigation. How i can achieve the same in windows 8. Can any one suggest a better method to achieve the same in windows 8. I found a solution, where we override onnavigated events in vm and handle navigate to other page. But i think that method is obsolete. Any one please guide me with the proper implementation. Thanks in advance.

like image 337
Rakesh R Nair Avatar asked Jun 10 '12 18:06

Rakesh R Nair


2 Answers

I understand this is not the exact answer you may be looking for, but this may give you some ideas to explore.

In my case, I'm not using MVVMLight - but my own simple MVVM implementation. I use the BindableBase class (which comes with the default VS 2012 RC templates) for property notifications. I imagine, you could use MVVMLight to give you some of the infrastructure, which you can complement with something like the below.

For navigation, I define an interface that looks like:

public interface INavigationService
{
    void Navigate(Type type);
    void Navigate(Type type, object parameter);
    void EnsureNavigated(Type pageType, object parameter);

    bool CanGoBack { get; }
    bool CanGoForward { get; }
    void GoBack();
    void GoForward(); 

    IView CurrentView { get; }
}

And implement it as follows:

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();
}

Finally, in the XAML page, define a Frame element:

<Frame x:Name="ContentFrame" />

And in the code-behind of the page: (this in the only ugly part in my opinion - but its hopefully not too bad):

var _navigationService = new NavigationService(this.ContentFrame);

You can now pass the _navigationService to the viewmodel. In my case I create the viewmodel in the code-behind of the page:

public HomePage()
{
    this.InitializeComponent();

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

    DataContext = new HomePageViewModel(_navigationService);

}

Hope this helps.

like image 188
Krishna Avatar answered Oct 29 '22 02:10

Krishna


Read the article published in MSDN Magazine just recently by Laurent Bugnion himself on working with the MVVM Light Toolkit and Windows 8.

Towards the end of the article he explains exactly how to setup the NavigationService you need.

http://msdn.microsoft.com/en-us/magazine/jj651572.aspx

like image 41
GONeale Avatar answered Oct 29 '22 02:10

GONeale