Forum Xamarin Xamarin.Forms

How to cancel navigation using OnNavigation override method? (Application Using Shell)

DenniroDenniro Member ✭✭

Hi to all,
I want to cancel a navigation due to validation reasons.
I find a method Cancel() from ShellNavigatingEventArgs parameter object in OnNavigating method but it doesn't work.
With the help of the debug mode i can check that even the Canceled property is change from false to true after using the Cancel() method. The Navigation continues anyway.

What am i missing here? Should i use other way to cancel the navigation ?

Regards.

Answers

  • LandLuLandLu Member, Xamarin Team Xamurai

    How did you use this method? I tested it with the official template it worked.
    I override it in Shell class like:

    public partial class AppShell : Xamarin.Forms.Shell
    {
        public AppShell()
        {
            InitializeComponent();
        }
    
        protected override void OnNavigating(ShellNavigatingEventArgs args)
        {
            base.OnNavigating(args);
    
            if (args.Target.Location.OriginalString.Contains("ItemDetailPage"))
            {
                args.Cancel();
            }
        }
    }
    

    The detail page can't be navigated to:

    When I changed it like:

    protected override void OnNavigating(ShellNavigatingEventArgs args)
    {
        base.OnNavigating(args);
    
        if (args.Source == ShellNavigationSource.Pop)
        {
            args.Cancel();
        }
    }
    

    Then detail page can't be poped:

    I used Xamarin Forms 4.4.0.991640

  • DenniroDenniro Member ✭✭

    OK.

    Try this code bellow:

    ` protected override async void OnNavigating(ShellNavigatingEventArgs args)
    {
    base.OnNavigating(args);
    if (args.Target.Location.OriginalString.Contains("ItemDetailPage"))
    {
    await SomeTaskAsync();
    args.Cancel();
    }
    }

        public async Task SomeTaskAsync()
        {
            await Task.Delay(2000);
        }`
    

    When i use it with synchronous code the navigation cancel works. But on asynchronous task the navigation proceed without waiting the task to complete. That is my issue. The ideal scenario is that the validation may take some time geting data from local or remote database and i would like to not block the UI thread. Do you know why is it happening ? It's a bug or it is on purpose? If it is on purpose you have any workaround?

    Thanks

  • LandLuLandLu Member, Xamarin Team Xamurai

    It seems the args.Cancel(); should be called immediately in the OnNavigating. If you want to add some conditions before popping, try:

    bool stopNavigating = true;
    protected async override void OnNavigating(ShellNavigatingEventArgs args)
    {
        base.OnNavigating(args);
    
        if (args.Source == ShellNavigationSource.Pop && stopNavigating)
        {
            args.Cancel();
            await SomeTaskAsync();
            stopNavigating = false;
            if (...)
            {
               await Navigation.PopAsync(); 
            }                      
        }
    }
    protected override void OnNavigated(ShellNavigatedEventArgs args)
    {
        base.OnNavigated(args);
    
        stopNavigating = true;
    }
    

    For the scenario when you want to navigate to the next page, we will verify the conditions first before running navigating code.

  • DenniroDenniro Member ✭✭

    OK. That is true. The args.Cancel(); should be called immediately.
    Another issue that i am facing regarding on Shell Navigation is with the first Navigation on the application. I notice that the OnNavigating method is fired before the AppShell Contructor completed. That's create a problem for me. Because i want to override the first navigation of the app and when i do that the app crashes. Can you confirm that? Do you have any workaround ?

    Thank you!

  • LandLuLandLu Member, Xamarin Team Xamurai

    It is by design.
    What do you want to set up in the OnNavigating event?

  • DenniroDenniro Member ✭✭

    I would like to make a proper navigation when a user tap the notification message. I see that OnAppearing method in the AppShell does not trigger. So i need to find a place to set the navigation code for the user. The code need to be in a specific place where all conditions of Notification Tap fulfilled. One is when the app is not running and the other one is when is when the app is in background. Do you have any idea?
    Thanks

  • LandLuLandLu Member, Xamarin Team Xamurai

    Notification is another thing.
    For iOS the event below in the AppDelegate will be called when the user tapped the notification to open the application:

    public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
    {
        // ...
    }
    

    This event will be triggered no matter the application is quit or at the background state.
    There are two conditions on Android. When the application is active, OnMessageReceived event of the firebase service will be called.
    However, when it is closed you need to use an extra activity to handle this behavior.
    Define an IntentFilter for the new activity:

    [IntentFilter(new[] { ".Activities.SecondActivity" }, Categories = new[] { "android.intent.category.DEFAULT" })]
    

    And this name should match with what you set in the notification payload's click_action property.

  • DenniroDenniro Member ✭✭

    I use xamarin forms and i would like to make things cross platform if it is possible. So i use Plugin.FirebasePushNotification where i can capture the notification message in all scenarios and both of platforms. So depending on the message i would like to navigate into a different screen. At Master Detail page version of my app, i managed to succeed the navigation by setting the navigation code inside the OnAppearing method of the detailed page because that method will be used in any scenarios. I would like to do something similar with an app shell app. As i can see from this https://github.com/xamarin/Xamarin.Forms/issues/6486 the AppShell 's OnAppearing method doesn't work right now but maybe it is going to be fixed. So maybe my solution rely on the OnAppearing method. In order to simplify the task that i am going to solve is how can i make a navigation at the start of the application automatically(without the user interaction).

  • LandLuLandLu Member, Xamarin Team Xamurai

    This plugin has an event called CrossFirebasePushNotification.Current.OnNotificationOpened you could perform the navigation there.
    The OnAppearing of Shell itself won't be triggered but the OnAppearing event of its pages will be called. If you do want to make the navigation in the shell you could put it on the first page of the Shell.

  • DenniroDenniro Member ✭✭

    I can not perform any navigation with CrossFirebasePushNotification.Current.OnNotificationOpened event because the event triggers before the initialization of the AppShell. If the app is closed, i can use the OnAppearing of first page of the Shell but when the app is in background, there are changes that the user will left the app in the background on the different page from the first one. So the navigation won't happen for sure.

  • LandLuLandLu Member, Xamarin Team Xamurai

    If OnNotificationOpened is called before the initialization we could persist this state using Properties. When the application hits the initialization, check the value of that state to determine whether we need to navigate to a new page.
    If OnNotificationOpened is called when the application is active, we could use Shell navigation directly to open a certain page.

  • sisaackssisaacks Member ✭✭✭

    I also have a question about this, If the tab I am navigating from has dirty data I want to cancel the navigation. But short of having a global variable, how can I tell if the tab has dirty data? I cant seem to find a way to access the tab from here?

  • sisaackssisaacks Member ✭✭✭

    Meaning I am currently in the OnNavigating method, I want to cancel the navigation if the tab has any dirty data

Sign In or Register to comment.