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:
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
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using Cirrious.MvvmCross.ExtensionMethods; | |
using Cirrious.MvvmCross.Interfaces.ViewModels; | |
using Cirrious.MvvmCross.Plugins.Json; | |
using Cirrious.MvvmCross.ViewModels; | |
namespace Casino.Core.ViewModels | |
{ | |
public abstract class BaseViewModel : MvxViewModel | |
{ | |
protected void RequestNavigate<TViewModel>(NavigationParametersBase parameters) | |
where TViewModel : IMvxViewModel | |
{ | |
var json = this.GetService<IMvxJsonConverter>(); | |
var text = json.SerializeObject(parameters); | |
this.RequestNavigate<TViewModel>( | |
new Dictionary<string, object>() | |
{ | |
{ NavigationParametersBase.Key, text} | |
}); | |
} | |
} | |
} |
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Windows.Input; | |
using Cirrious.MvvmCross.Commands; | |
using Cirrious.MvvmCross.Platform.Diagnostics; | |
namespace Casino.Core.ViewModels | |
{ | |
public class HomeViewModel : BaseViewModel | |
{ | |
public void Init() | |
{ | |
MvxTrace.Trace("Initialising HomeViewModel ... with no parameters"); | |
} | |
public ICommand GoCommand | |
{ | |
get | |
{ | |
return new MvxRelayCommand(() => this.RequestNavigate<SubViewModel>(new SubViewModel.NavigationParameters() { Test1 = "Testing 1", Test2 = 99 })); | |
} | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Cirrious.MvvmCross.Platform.Diagnostics; | |
namespace Casino.Core.ViewModels | |
{ | |
public class SubViewModel : BaseViewModel | |
{ | |
public class NavigationParameters : NavigationParametersBase | |
{ | |
public string Test1 { get; set; } | |
public int Test2 { get; set; } | |
} | |
public SubViewModel() | |
{ | |
MvxTrace.Trace("Constructing..."); | |
} | |
public void Init(NavigationParameters parameters) | |
{ | |
MvxTrace.Trace("Initialising SubViewModel ... with parameters {0} and {1}", parameters.Test1, parameters.Test2); | |
} | |
} | |
} |
Now, create a default ViewModelLocator which can deserialise the incoming NavigationParameters and can initialise the ViewModel:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Collections.Generic; | |
using Cirrious.MvvmCross.Application; | |
using Cirrious.MvvmCross.ExtensionMethods; | |
using Cirrious.MvvmCross.Interfaces.Platform.Diagnostics; | |
using Cirrious.MvvmCross.Interfaces.ViewModels; | |
using Cirrious.MvvmCross.Platform.Diagnostics; | |
using Cirrious.MvvmCross.Plugins.Json; | |
namespace Casino.Core.ViewModels | |
{ | |
public class CustomViewModelLocator | |
: MvxBaseViewModelLocator | |
{ | |
public override bool TryLoad(Type viewModelType, IDictionary<string, string> parameterValueLookup, out IMvxViewModel model) | |
{ | |
model = null; | |
// create the new ViewModel | |
// here we use Activator.CreateInstance but this could also be done using an IoC container | |
var newViewModel = Activator.CreateInstance(viewModelType); | |
// find the NavgiateTo method | |
var initMethod = viewModelType.GetMethod("Init"); | |
if (initMethod == null) | |
{ | |
MvxTrace.Trace(MvxTraceLevel.Error, "Missing Init method in ViewModel"); | |
return false; | |
} | |
var navigateToParameters = initMethod.GetParameters(); | |
if (navigateToParameters.Length > 1) | |
{ | |
MvxTrace.Trace(MvxTraceLevel.Error, "Missing Init method has too many parameters {0} - expecting zero or one", navigateToParameters.Length); | |
return false; | |
} | |
if (navigateToParameters.Length == 0) | |
{ | |
initMethod.Invoke(newViewModel, new object[0]); | |
} | |
else | |
{ | |
var navigationParameter = navigateToParameters[0]; | |
if (!typeof(NavigationParametersBase).IsAssignableFrom(navigationParameter.ParameterType)) | |
{ | |
MvxTrace.Trace(MvxTraceLevel.Error, "The parameter for NavigateTo must inherit from NavigationParametersBase"); | |
return false; | |
} | |
if (!parameterValueLookup.ContainsKey(NavigationParametersBase.Key)) | |
{ | |
MvxTrace.Trace(MvxTraceLevel.Error, "The Navigaton was missing the parameter for {0}", NavigationParametersBase.Key); | |
return false; | |
} | |
var text = parameterValueLookup[NavigationParametersBase.Key]; | |
var json = this.GetService<IMvxJsonConverter>(); | |
var navigationParameterObject = json.DeserializeObject(navigationParameter.ParameterType, text); | |
initMethod.Invoke(newViewModel, new object[] {navigationParameterObject}); | |
} | |
model = (IMvxViewModel)newViewModel; | |
return true; | |
} | |
} | |
} |
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:
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Casino.Core.ViewModels; | |
using Cirrious.MvvmCross.Application; | |
using Cirrious.MvvmCross.ExtensionMethods; | |
using Cirrious.MvvmCross.Interfaces.ServiceProvider; | |
using Cirrious.MvvmCross.Interfaces.ViewModels; | |
namespace Casino.Core | |
{ | |
public class App | |
: MvxApplication | |
, IMvxServiceProducer | |
{ | |
public App() | |
{ | |
// set the start object | |
var startApplicationObject = new StartApplicationObject(); | |
this.RegisterServiceInstance<IMvxStartNavigation>(startApplicationObject); | |
} | |
protected override IMvxViewModelLocator CreateDefaultViewModelLocator() | |
{ | |
return new CustomViewModelLocator(); | |
} | |
} | |
} |
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