Here's a full implementation example that would solve the problem by adding a new interface that fully replaces the one from MvvmLight and also allows you to choose whether to use animations or not. In this example, we add the ability to control whether the navigation should be animated or not:
Interface
public interface ICustomNavigationService
{
string CurrentPageKey { get; }
void GoBack(bool animate = true);
void NavigateTo(string pageKey, bool animate = true);
void NavigateTo(string pageKey, object parameter, bool animate = true);
}
Implementation
public class NavigationService : ICustomNavigationService
{
private readonly Dictionary<string, Type> _pagesByKey = new Dictionary<string, Type>();
private NavigationPage _navigation;
public NavigationPage Navigation
{
get
{
return _navigation;
}
}
public string CurrentPageKey
{
get
{
lock (_pagesByKey)
{
if (_navigation.CurrentPage == null)
{
return null;
}
var pageType = _navigation.CurrentPage.GetType();
return _pagesByKey.ContainsValue(pageType)
? _pagesByKey.First(p => p.Value == pageType).Key
: null;
}
}
}
public void GoBack(bool animate = true)
{
_navigation.PopAsync(animate);
MessagingCenter.Send<INavigationService>(this, "NAVIGATING");
}
public void NavigateTo(string pageKey, bool animate = true)
{
NavigateTo(pageKey, null, animate);
MessagingCenter.Send<INavigationService>(this, "NAVIGATING");
}
public void NavigateTo(string pageKey, object parameter, bool animate = true)
{
lock (_pagesByKey)
{
if (_pagesByKey.ContainsKey(pageKey))
{
var type = _pagesByKey[pageKey];
ConstructorInfo constructor;
object[] parameters;
if (parameter == null)
{
constructor = type.GetTypeInfo()
.DeclaredConstructors
.FirstOrDefault(c => !c.GetParameters().Any());
parameters = new object[]
{
};
}
else
{
constructor = type.GetTypeInfo()
.DeclaredConstructors
.FirstOrDefault(
c =>
{
var p = c.GetParameters();
return p.Count() == 1
&& p[0].ParameterType == parameter.GetType();
});
parameters = new[]
{
parameter
};
}
if (constructor == null)
{
throw new InvalidOperationException(
"No suitable constructor found for page " + pageKey);
}
var page = constructor.Invoke(parameters) as Page;
_navigation.PushAsync(page, animate);
}
else
{
throw new ArgumentException(
string.Format(
"No such page: {0}. Did you forget to call NavigationService.Configure?",
pageKey),
"pageKey");
}
}
}
public void Configure(string pageKey, Type pageType)
{
lock (_pagesByKey)
{
if (_pagesByKey.ContainsKey(pageKey))
{
_pagesByKey[pageKey] = pageType;
}
else
{
_pagesByKey.Add(pageKey, pageType);
}
}
}
public void Initialize(NavigationPage navigation)
{
_navigation = navigation;
}
}
From here, you can add other methods you would like. Make sure to inject this or use it directly where you were using your MvvmLight one before.
integrate it with the MVVM light
? You can just create your ownICustomNavigationService
interface, implement it for the various OS's, and then register the implementation in theSimpleIoc
container. If you are not that familiar how navigation is done in the different platforms you can look at the source code here mvvmlight.codeplex.com/SourceControl/latest and see how it is done by the author ofMVVM light
– GreaterISharathNavigationService
, and define all needed operations. You use this interface in your shared code. Then you implement it on each platform; (WindowsNavigationService
or similar) and register the implementation to the interface with theSimpleIoc
container (likeSimpleIoc.Default.Register<ISharathNavigationService, WindowsNavigationService>()
). Finally in your shared code you call theSimpleIoc
container for the instance of theISharathNavigationService
(similar toSimpleIoc.Default.GetInstance<ISharathNavigationService>()
) – GreaterMVVM light
). – Greater