Wednesday, January 02, 2013

Navigating between ViewModels by more than just strings...

One of the questions that has come up a few times on StackOverflow is about why MvvmCross insists on using Strings for ViewModel navigation parameters.

The answer to this has always been that these are used in order to ensure that the navigation can be serialised down into a Xaml Uri or into an Android Intent. e.g. see the question and answer in http://stackoverflow.com/questions/10192505/passing-on-variables-from-viewmodel-to-another-view-mvvmcross

The good news is that from a checkin on New Year's Eve, strings are now not the only option - you can now use:
  • string
  • long
  • int
  • double
  • your own custom enums

To see the changes that enabled this, see the commit at: https://github.com/slodge/MvvmCross/commit/bbe73cfcc0e290533656ab6d862c787c7fbae04a

For an example of integer use, see the way I modified the Conference sample: https://github.com/slodge/MvvmCross/commit/c5e0be6728f855810f8f6d19d6b92dd84cb3d26c

--------------

These changes, however, still ask the user to use lists of parameters.... and these parameters lists can get quite long...

One request on Jabbr was:

  • gshackles:

    one of the things I don't like is that i'm just passing these anonymous objects around with magic properties

    would prefer to have a class for the parameters to a view model and just pass that in

    would also make it much more resistant to refactoring too

This seemed like a very reasonable request.... and the good news is that you can add this yourselves by:
  • overriding the way navigations are requested 
  • and overriding the way ViewModels are located.

Here's one way to achieve this:

First, create the base type for all your navigation parameter objects


Then modify your BaseViewModel (or ViewModelBase) in order to allow it to support this parameter object navigation


Now modify each of your view models so that they have a new NavigateTo method - which either take no argument or which take a class derived from NavigationParametersBase:


Now, create a default ViewModelLocator which can deserialise the incoming NavigationParameters and can initialise the ViewModel:


Note that this method uses a new deserialise method - only just added: https://github.com/slodge/MvvmCross/commit/f329a2ee6b68809060a52674b924549156d8c9b1

Finally, to make sure that the locator is used, override CreateDefaultViewModelLocator in your MvxApplication:


That's it.

Obviously, there's more that could be done - and different ways in which the ViewModel could be initialised - but this is a basic start which others can build on if they want to.

No comments:

Post a Comment