Rob
Rob

Reputation: 1390

OnNavigatedTo in ViewModel isn't firing when page first loads

I'm trying to implement Azure Active Directory B2C in Xamarin.Forms. If I just copy their example, I can get it to work without a problem. But when I try to use Prism, I run into problems.

I took this code that was sitting in the codebehind of the XAML:

protected override async void OnAppearing ()
{
    base.OnAppearing ();
    App.PCApplication.PlatformParameters = platformParameters;

    try {
        var ar = await App.PCApplication.AcquireTokenSilentAsync(
            AuthenticationInfo.Scopes, string.Empty, AuthenticationInfo.Authority,
            AuthenticationInfo.SignUpSignInpolicy, false);

        AuthenticationInfo.UserAuthentication = ar;
    } catch {               
    }
}

async void OnSignUpSignIn(object sender, EventArgs e)
{
    try {
        var ar = await App.PCApplication.AcquireTokenAsync(
            AuthenticationInfo.Scopes, string.Empty, UiOptions.SelectAccount,
            string.Empty, null, AuthenticationInfo.Authority,
            AuthenticationInfo.SignUpSignInpolicy);

        AuthenticationInfo.UserAuthentication = ar;
    } catch (Exception ex) {
        if (ex != null) {
        }               
    }
}

and moved it to the ViewModel's OnNavigatedTo:

public async void OnNavigatedTo (NavigationParameters parameters)
        {
            if (parameters.ContainsKey ("title"))
                Title = (string)parameters ["title"];

            listen2asmr.App.PCApplication.PlatformParameters = platformParameters;

            try {
                var ar = await listen2asmr.App.PCApplication.AcquireTokenSilentAsync(
                    AuthenticationInfo.Scopes, string.Empty, AuthenticationInfo.Authority,
                    AuthenticationInfo.SignUpSignInpolicy, false);

                AuthenticationInfo.UserAuthentication = ar;
            } catch {

            }
        }

This is in the Bootstrapper:

protected override Xamarin.Forms.Page CreateMainPage ()
        {
            return Container.Resolve<LoginPage> ();
        }

        protected override void RegisterTypes ()
        {
            Container.RegisterTypeForNavigation<LoginPage>();
        }

OnNavigatedTo never seems to get called though. Is there some other method I should be using, or did I miss something else? The only other thing I could think of was to call the code in OnNavigatedTo from the ViewModel constructor, but the async/await does work with the constructor.

Upvotes: 0

Views: 1387

Answers (2)

user5420778
user5420778

Reputation:

This has been fixed in the latest preview version of Prism for Xamarin.Forms. Try using these packages instead:

https://www.nuget.org/packages/Prism.Forms/6.1.0-pre4 https://www.nuget.org/packages/Prism.Unity.Forms/6.2.0-pre4

Also the bootstrapping process has changed. Read this for more information:

Upvotes: 1

C. McCoy IV
C. McCoy IV

Reputation: 897

My advice is use your View events as triggers for your ViewModel.

For Instance:

View.xaml.cs

protected override async void OnAppearing () {
    base.OnAppearing ();
    viewModel.OnAppearing();
}

async void OnSignUpSignIn(object sender, EventArgs e) {
     viewModel.OnSignUpSignIn(sender, e);
} 

ViewModel.cs

protected override async void OnAppearing () {
    App.PCApplication.PlatformParameters = platformParameters;

    try {
        var ar = await App.PCApplication.AcquireTokenSilentAsync(
            AuthenticationInfo.Scopes, string.Empty,
            AuthenticationInfo.Authority,
            AuthenticationInfo.SignUpSignInpolicy, false);

        AuthenticationInfo.UserAuthentication = ar;
    } catch {               
    }
}

async void OnSignUpSignIn(object sender, EventArgs e) {
     try {
         var ar = await App.PCApplication.AcquireTokenAsync(
            AuthenticationInfo.Scopes, string.Empty, 
            UiOptions.SelectAccount,
            string.Empty, null, AuthenticationInfo.Authority,
            AuthenticationInfo.SignUpSignInpolicy);

         AuthenticationInfo.UserAuthentication = ar;
    } catch (Exception ex) {
        if (ex != null) {
        }               
    }
} 

Reasons:

  1. View should only involve visuals, and the events your page receives. Logic should be forwarded to the ViewModel, unless it deals with representation of information (for instance, logic to use a toggle-box for 2 choices but a combo-box for 3+).

  2. Nearly vice-versa, the ViewModel should keep track of "model state" (ex. the user still needs to enter their payment information) as opposed to "view state" (ex. the user has navigated to the payment page).

Upvotes: 0

Related Questions