xamarin.formsfreshmvvm

Opening a Page in FreshMVVM from a Push Notification and onward Navigation


I am trying to open a page using FreshMVVM. If the app is already running I want to plug into the exisiting navigation stack.

The page opens fine but when we try and navigate the user onward by pushing a new page onto the stack i get the following Exception

FreshTinyIoC.TinyIoCResolutionException: 'Resolve failed: IFreshNavigationService'

With a Call Stack of:

 at FreshTinyIoC.FreshTinyIoCContainer.ResolveInternal (FreshTinyIoC.FreshTinyIoCContainer+TypeRegistration registration, FreshTinyIoC.NamedParameterOverloads parameters, FreshTinyIoC.ResolveOptions options) [0x00136] in <244cbb4b2b78473caee762c4138df3f3>:0 
 at FreshTinyIoC.FreshTinyIoCContainer.Resolve (System.Type resolveType, System.String name) [0x00013] in <244cbb4b2b78473caee762c4138df3f3>:0 
 at FreshTinyIoC.FreshTinyIoCContainer.Resolve[ResolveType] (System.String name) [0x00001] in <244cbb4b2b78473caee762c4138df3f3>:0 
 at FreshMvvm.FreshTinyIOCBuiltIn.Resolve[ResolveType] (System.String name) [0x00006] in <c1f1d60a460941bc82899cfb78f0c2ec>:0 
 at FreshMvvm.PageModelCoreMethods.PushPageModelWithPage (Xamarin.Forms.Page page, FreshMvvm.FreshBasePageModel pageModel, System.Object data, System.Boolean modal, System.Boolean animate) [0x001ca] in <c1f1d60a460941bc82899cfb78f0c2ec>:0 

This comes from the following call to PushPageModel

return new FreshAwaitCommand(async (entryType, tcs) =>
{
    await this.CoreMethods.PushPageModel(typeof(SignalHistoryViewModel), null, false, true);
    tcs.SetResult(true);
});

The code I use to load the page when responding to the Notifcation tap is below. Note if there is not an existing Navigation I create a new container, if there is an existing one I want to Push onto that one. I am assuming that FreshMVVM is correctly initialised because otherwise I would not be able to load the first page after the tapping on Notification. The exception only throws when I try and load then next Page

Type viewModelType = Helpers.SignalStateToViewModelHelper.GetSignalDetailViewModelType((State)Enum.Parse(typeof(State), signalState));

var navigationStack = Application.Current.MainPage as NavigationPage;

if (navigationStack != null)
{
    // Navigate within the existing navigation stack
    var pageModel = FreshPageModelResolver.ResolvePageModel(viewModelType, true);

    Device.BeginInvokeOnMainThread(async () =>
    {
        await navigationStack.PushAsync(FreshPageModelResolver.ResolvePageModel(viewModelType, null));
    });
}
else
{
    // Create a new navigation stack
    var pageModel = FreshPageModelResolver.ResolvePageModel(viewModelType, true);
    var navigationContainer = new FreshNavigationContainer(pageModel);

    Device.BeginInvokeOnMainThread(() =>
    {
        Application.Current.MainPage = navigationContainer;
    });
}

If I always create a new container the code never fails but that means it is a new Navigation and I cannot press back in the stack.


Solution

  • I solved this by explicitly registering a IFreshNavigationService.

    FreshIOC.Container.Register<IFreshNavigationService>(freshNavigationContainer, Constants.DefaultNavigationServiceName);

    This might sound like a "Doh!" or RTFM moment but it still surprises me because I am pushing the page into a running instance that obviously does have an IFreshNavigationService registered otherwise it would not have worked up to that point.

    I can only assume that this is because I do properly understand the App lifecycle and when the page is created in code running from a Notification "delegate" it is running in a different context.