1

I have been through multiple articles on navigation and passing parameters with prism. However, nothing I try will make the OnNavigatingTo method fire when changing pages.

My goal is to pass a simple parameter from the LoginPage to the MultifactorAuthPage.

If I try and get the parameter in the OnNavigatingTo method thee app will not change pages for some reason. It will hit the breakpoint and just stay on the LoginPage.

I'm currently using Xamarin Forms 3.6 with Prism 7.1.

Here's some of my code:

LoginPageViewModel

    public LoginPageViewModel(INavigationService navigationService, IPushNotification pushNotification)
    {
        _navigationService = navigationService;
        LoginCommand = new DelegateCommand(BeginLoginAsync);
    }
    private async void BeginLoginAsync()
    {
        await _navigationService.NavigateAsync("MultifactorAuthPage", new NavigationParameters("PhoneNumber=9999999999"));
    }

MultifactorAuthViewModel

public class MultifactorAuthPageViewModel : ViewModelBase, INavigationAware
{
    INavigationService _navigationService;

    public MultifactorAuthPageViewModel(INavigationService navigationService)
    {
        _navigationService = navigationService;
    }

    private override void OnNavigatingTo(INavigationParameters parameters)
    {

    }

    private override void OnNavigatedFrom(INavigationParameters parameters)
    {

    }

    private override void OnNavigatedTo(INavigationParameters parameters)
    {
        PhoneNumber = Convert.ToInt32(parameters["PhoneNumber"]);
    }

}

ViewModelBase

public class ViewModelBase : BindableBase, INavigationAware
{

    public ViewModelBase()
    {
    }

    public virtual void OnNavigatedFrom(INavigationParameters parameters)
    {

    }

    public virtual void OnNavigatedTo(INavigationParameters parameters)
    {

    }

    public virtual void OnNavigatingTo(INavigationParameters parameters)
    {

    }

}

Some of the resources I've tried:

https://prismlibrary.github.io/docs/xamarin-forms/navigation/passing-parameters.html https://xamgirl.com/prism-in-xamarin-forms-step-by-step-part-2/ https://github.com/PrismLibrary/Prism-Samples-Forms/tree/master/ContosoCookbook

TheNameHobbs
  • 679
  • 7
  • 21
  • 36
  • Are you doing anything custom as far as registering the INavigationService with the DI container? The only difference between my setup, which is working, and yours, from what I can see, is that I'm passing INavigationService down into the base constructor, and keeping it as a protected property on ViewModelBase. – Max Hampton Apr 23 '19 at 16:20
  • I don't think so. I have this in my register types: containerRegistry.RegisterForNavigation(); And I do this in App.cs: await NavigationService.NavigateAsync("NavigationPage/LoginPage"); – TheNameHobbs Apr 23 '19 at 19:27
  • Have you registered your other pages for navigation using `containerRegistry.RegisterForNavigation("LoginPage")` – Max Hampton Apr 23 '19 at 19:53
  • Yes. I created a new sample project and the code works. I'm not sure where the disconnect is in my project. – TheNameHobbs Apr 23 '19 at 20:20

3 Answers3

0

Your BeginLoginAsync method is obviously asynchronous. Therefore you need to instantiate the command to be asynchronous as well. Try this:

public LoginPageViewModel(INavigationService navigationService, IPushNotification pushNotification)
{
        _navigationService = navigationService;
        LoginCommand = new DelegateCommand(async () => await BeginLoginAsync());
}

also you need to change the BeginLoginAsync method in order to return a Task instead of void.

private async Task BeginLoginAsync()
{
    await _navigationService.NavigateAsync("MultifactorAuthPage", new NavigationParameters("PhoneNumber=9999999999"));
}

Then you should be fine.

EDIT: Also try and change this method signature to be async if you have to await and don't forget to call the base methods:

public override async void OnNavigatingTo(INavigationParameters parameters)
{
   ...
   base.OnNavigatingTo(parameters);
}

Hope it helps & happy coding!

TaiT's
  • 3,138
  • 3
  • 15
  • 26
  • That didn't work unfortunately. It navigates to the multi-factor page fine but it does not fire the event. Weird – TheNameHobbs Apr 23 '19 at 13:35
  • You miss calls to base.OnNavigatXXXXX(parameters); in every method – TaiT's Apr 23 '19 at 14:20
  • So OnNavigatingTo and OnNavigatedTo are being hit in the LoginViewModel when the app loads. When i try and go to the multi-factor page, only the OnNavigatingTo method is hit (not the OnNaviagtedTo). Then If i click the back arrow in the navigation bar, OnNavigatedTo is hit again in the LoginViewModel. So something must be off with my MultifactorViewModel – TheNameHobbs Apr 23 '19 at 14:51
  • These suggestions are good, but don't really address the question. Calling through to base.OnNav... won't have any effect, he'd be calling through to empty virtual methods. async void methods are also perfectly fine as delegates passed into commands, they behave the same as async event handlers, the other case where async void is acceptable. – Max Hampton Apr 23 '19 at 16:14
0

Turns out it was failing silently due to the int value overflowing. Silent exceptions are killers

TheNameHobbs
  • 679
  • 7
  • 21
  • 36
  • Something you might consider here is registering an ILoggerFacade implementation with the DI container. Prism does its logging against that interface, it can help you diagnose a lot of those navigation issues that fail silently. – Max Hampton Apr 25 '19 at 17:31
  • Do you have any links on that implementation? – TheNameHobbs Oct 02 '19 at 03:58
  • Prism defines the ILoggerFacade interface: https://github.com/PrismLibrary/Prism/blob/master/Source/Prism/Logging/ILoggerFacade.cs. Implement that single Log method on a class, register it with the container for service type ILoggerFacade, and Prism will use that class for internal logging. My implementation takes my "real" logger as a dependency, and calls through to the "real" logger. – Max Hampton Oct 02 '19 at 16:25
0

So old question, but i was fighting with a similar issue today, and my problem was some kind of silent exception. So I'll share my problem and solution, maybe helps..

In my case, i have a method for viewModel initialization that's paired with a command to do "re-initializations" in response to user actions inside page. So, that method is called inside "OnNavigateTo" and can be invoked by a command in response to user actions. But OnNavigateTo was not firing...

As my Initialization method receives an int32 parameter, first I had a delegate command like this:

 public DelegateCommand<int> DoInitialization{ get; set; }

The problem for me was with command instantiation in viewModel constructor: it failed silently and code stops, and the reason is you can only use reference types with commands, so, i changed my DelegateCommand to:

 public DelegateCommand<int?> DoInitialization{ get; set; }

... make it nullable is enough to have a reference type, and problem disappears. Yes, is obvious for experienced xamarin/prism programmers, but not for newbies like me, as you does not receive any exception.

Regards.

Fran CD
  • 167
  • 3
  • 11