Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the best way to handle GoBack for the different MvvmCross (v3) platforms

Tags:

c#

mvvmcross

In MvvmCross v3 I use ShowViewModel to navigate to different pages. Before converting over to Mvx I'd use the NavigationService.GoBack() method to go back to the previous page. The advantage being that the page isn't re-created.

Since the GoBack method is platform specific to WP, WInRT, Silverlight, what is the best way to handle returning to the previous page so the view model remains platform independent?

One solution might be to use ShowViewModel passing some data that the view can see and then in the case of WP/WinRT, calling RemoveBackEntry from the view. But with Mvx, there's probably a better way.

like image 360
Derek Beattie Avatar asked Apr 22 '13 22:04

Derek Beattie


2 Answers

In MvvmCross v3, we provided a specific mechanism to allow ViewModels to send messages to the UI that they would like to change the current presentation.

This mechanism is ChangePresentation(MvxPresentationHint hint) and it provides routing of messages - presentation hints - from ViewModels to the Presenter.

How the Presenter handles these messages is platform and application specific.

This message mechanism is very general and it might be used for all sort of things in the future - e.g. devs might supply hints which do things like change the UI layout, which highlight part of the UI, which force the user focus on to a certain control, which cause the SIP to be displayed or hidden, etc.


For the case of closing a view model, we have provided a specialisation of MvxPresentationHint - MvxClosePresentationHint - and a helper method in a base class of MvxViewModel:

    protected bool Close(IMvxViewModel viewModel)
    {
        return ChangePresentation(new MvxClosePresentationHint(viewModel));
    }

To use this a ViewModel can just call Close(this)

When this is called, the Presenter within your UI will receive a message on the ChangePresentation method:

public interface IMvxViewPresenter
{
    void Show(MvxViewModelRequest request);
    void ChangePresentation(MvxPresentationHint hint);
}

For the general/typical case - where the ViewModel that is being closed is attached to the view which is the topmost Activity/Page/UIViewController, the default presenters within MvvmCross will be able to handle this message and will be able to GoBack in Windows, to Finish in Android, and to PopViewController in iOS.

However, if your UI is more complicated than that - e.g. if the ViewModel you want to Close actually corresponds to a Tab, to a Flyout, to a SplitView pane, etc, or if the ViewModel corresponds to something other than the current topmost view in the hierarchy - then you will need to provide a custom presenter implementation - and that implementation will have to do platform and application specific logic to handle the Close.


The above hint is what I recommend you use...

However, as an alternative:

If you were to feel this ChangePresentation(MvxPresentationHint hint) mechanism was simply too heavyweight/overkill for your app, then you can also, of course, drop down to a custom or Message based mechanism instead.

One sample that does this is the CustomerManagement sample - it provides a custom IViewModelCloser implementation on each platform - see:

  • custom interface - https://github.com/slodge/MvvmCross/blob/v3/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement/Interfaces/IViewModelCloser.cs
  • BaseViewModel - https://github.com/slodge/MvvmCross/blob/v3/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement/ViewModels/BaseViewModel.cs
  • Droid - https://github.com/slodge/MvvmCross/blob/v3/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement.Droid/SimpleDroidViewModelCloser.cs
  • WP - https://github.com/slodge/MvvmCross/blob/v3/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement.WindowsPhone/ViewModelCloser.cs
  • Touch - https://github.com/slodge/MvvmCross/blob/v3/Sample%20-%20CustomerManagement/CustomerManagement/CustomerManagement.Touch/CustomerManagementPresenter.cs
like image 110
Stuart Avatar answered Oct 06 '22 03:10

Stuart


I'm not completely sure about mvvmcross, but in MVVM Light what is usually done is to create an INavigationService interface that exposes these methods.

Then, each platform implements this Interface in the platform-specific way (in WP for example by getting a reference to the current frame and its content). This platform specific instance can then do all the correct actions to make sure the navigation pattern is correctly implemented.

Your ViewModels can then get a reference to an instance of the INavigationService through a Dependency Container. That way your VM is independent on the platform specifics of navigation.

I also wrote a blog post on how to use Interfaces to expose a common API for platform specific features: http://www.kenneth-truyers.net/2013/02/24/patterns-for-sharing-code-in-windows-phone-and-windows-8-applications/

The example in the blog post is about Isolated Storage, but the same principles apply to Navigation (or any feature that has different implementations on various platforms for that matter)

like image 36
Kenneth Avatar answered Oct 06 '22 03:10

Kenneth