locked
OnNavigatedTo in Prism doesn't trigger from one of pages RRS feed

  • Question

  • User195916 posted

    Hello. I faced with the strange behavior of OnNavigatedTo in Prism. It works always on Android, but on iOS it not works for one of the pages. See code:

    private void OnSpecialtyTapped()
            {
                _navigationService.NavigateAsync($"{nameof(SpecialtyFilterPage)}", useModalNavigation: false);
            }
    
    private void OnLocationTapped()
            {
                _navigationService.NavigateAsync($"{nameof(PlacesFilterPage)}", useModalNavigation: false);
            }
    
    
    private void OnTakeChosenSpecialties()
            {
                var parameters = new NavigationParameters
                {
                    //{"ChosenSpecialtiesIds", CheckedSpecialties.Select(s => s.Id).ToList()}
                };
    
                _navigationService.GoBackAsync(parameters);
            }
    
    private void OnTakeChosenPlaces()
            {
                var parameters = new NavigationParameters
                {
                    //{"ChosenPlaces", CheckedPlaces.Select( p => new Models.PlaceParameter {Id=p.Id, Type=Convert.ToString(p.Type)}).ToList()}
                };
    
                _navigationService.GoBackAsync(parameters);
            }
    
    public void OnNavigatedTo(NavigationParameters parameters)
            {
                if ( parameters.ContainsKey("ChosenSpecialtiesIds") )
                {
                    var chosenSpecialtiestIds = parameters["ChosenSpecialtiesIds"] as List<string>;
                    if ( chosenSpecialtiestIds == null ) return;
                    _filter.Services.Clear();
    
                    foreach ( var specialtiestId in chosenSpecialtiestIds )
                    {
                        _filter.Services.Add(new ServiceParameter { Id = specialtiestId });
                    }
                }
                else if ( parameters.ContainsKey("ChosenPlaces") )
                {
                    var chosenPlaces = parameters["ChosenPlaces"] as List<PlaceParameter>;
                    if ( chosenPlaces == null ) return;
                    _filter.Places.Clear();
    
                    _filter.Places = chosenPlaces;
                }
    
            }
    

    It works with Specialty and doesn't work on iOS with Places. I am using Prism 6.2.0 and Xamarin.Forms 2.3.2.127. I can't use newer version because of some bug.

    @BrianLagunas Could you help with it?

    Also posted here: https://stackoverflow.com/questions/42484016/onnavigatedto-in-prism-doesnt-trigger-from-one-of-pages

    Monday, February 27, 2017 10:49 AM

Answers

  • User76049 posted

    @YuraBabiy @BrianLagunas

    Your issue is the custom renderer, you always set the font even when the uielement is been destroyed when the page is been popped of the navigation stack.

    Old code

    protected override void OnElementChanged(ElementChangedEventArgs<Label> e) { base.OnElementChanged(e); UpdateFormattedText(); }

    New code

    ``` protected override void OnElementChanged(ElementChangedEventArgs

            if (e.OldElement != null)
            {
                // unhook event handlers etc here
            }
    
            if (e.NewElement != null)
            {
                UpdateFormattedText();
            }
        }
    

    ```

    I stuck some debug statements in the filter viewmodel and BPage viewmodel to check the GoBackAsync was successfull.

    ```

            var res = await _navigationService.GoBackAsync(parameters);
            Debug.WriteLine("BPageViewModel GoBackAsync was successful: " + res.ToString());
    

    ```

    With the old renderer:

    [0:] BPageViewModel: OnNavigatingTo [0:] Filter OnNavigatedFrom [0:] BPageViewModel: OnNavigatedTo [0:] Filter OnNavigatingTo [0:] BPageViewModel GoBackAsync was successful: False [0:] BPageViewModel: OnNavigatingTo [0:] Filter OnNavigatedFrom [0:] BPageViewModel: OnNavigatedTo

    With the fixed renderer:

    [0:] BPageViewModel: OnNavigatingTo [0:] Filter OnNavigatedFrom [0:] BPageViewModel: OnNavigatedTo [0:] Filter OnNavigatingTo [0:] BPageViewModel: OnNavigatedFrom [0:] Filter OnNavigatedTo Thread started: #6 [0:] BPageViewModel GoBackAsync was successful: True Thread started: <Thread Pool> #7 Thread started: <Thread Pool> #8 [0:] BPageViewModel: OnNavigatingTo [0:] Filter OnNavigatedFrom [0:] BPageViewModel: OnNavigatedTo [0:] BPageViewModel: OnNavigatedFrom [0:] Filter OnNavigatedTo Thread finished: <Thread Pool> #8 The thread 'Unknown' (0x8) has exited with code 0 (0x0).

    In both test I did the following

    Navigate to Page B Navigate back via view button Navigate to Page B Navigate back via soft back button

    OnNavigatingTo to doesn't seem to get called if you do a software back (I think that's a Forms limitation), but the issue is due to your renderer causing the page to probably remain in memory.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Wednesday, March 1, 2017 2:52 PM

All replies

  • User76049 posted

    I haven't seen this behavior in 6.3 pre1 in iOS, Android or UWP.

    6.3 Pre2 has been released, try testing with that to see if it resolves your issue.

    Monday, February 27, 2017 11:40 AM
  • User195916 posted

    @NMackay I did a typo. I have 2.3.2.127. I can't update because of this bug: https://bugzilla.xamarin.com/show_bug.cgi?id=52247

    Monday, February 27, 2017 12:16 PM
  • User76049 posted

    @YuraBabiy

    Pre1 of prism for Forms should be okay with that version of Forms.

    https://www.nuget.org/packages/Prism.Forms/6.3.0-pre1

    Dependencies MonoAndroid 1.0 Prism.Core (>= 6.3.0-pre1) Xamarin.Forms (>= 2.3.2.127) MonoTouch 1.0 Prism.Core (>= 6.3.0-pre1) Xamarin.Forms (>= 2.3.2.127)

    I wouldn't install Prism 6.3 Pre2 as it has a dependency on a the latest stable build of Forms

    Xamarin.Forms (>= 2.3.3.193)

    Monday, February 27, 2017 12:59 PM
  • User195916 posted

    @NMackay It has been installed, but the behavior is the same.

    Monday, February 27, 2017 2:11 PM
  • User76049 posted

    @YuraBabiy

    not sure what's going on based on the info here.

    Out of interest, do it make any difference if you await the GoBack?

    ``` private async void OnTakeChosenPlaces() { var parameters = new NavigationParameters { //{"ChosenPlaces", CheckedPlaces.Select( p => new Models.PlaceParameter {Id=p.Id, Type=Convert.ToString(p.Type)}).ToList()} };

            await _navigationService.GoBackAsync(parameters);
        }
    

    ```

    Monday, February 27, 2017 2:26 PM
  • User195916 posted

    @NMackay No, I tried it before. I also have no idea.

    Monday, February 27, 2017 2:33 PM
  • User76049 posted

    @YuraBabiy

    It sounds very like this issue which has been closed.

    https://github.com/PrismLibrary/Prism/issues/460

    Monday, February 27, 2017 3:12 PM
  • User195916 posted

    @NMachay Yes, it looks similar. But my root page is not a start page. It is second in the stack. I'm navigating to it like so:

    _navigationService.NavigateAsync($"{nameof(FilterPage)}", useModalNavigation: false, parameters: parameters);

    Maybe it is related, but now it is even stranger. OnNavigatingTo doesn't fire on Android on both pages and on the root page (root I mean second in Filter). On iOS OnNavigatedTo same, OnNavigatingTo works even where OnNavigatedTo doesn't work.

    Monday, February 27, 2017 3:42 PM
  • User76049 posted

    @YuraBabiy

    Could you create a small repo? if I can recreate in my environment I'll ask on the slack channel if anyone is aware of this.

    Monday, February 27, 2017 10:33 PM
  • User116727 posted

    @YuraBabiy please provide a repo. I am unable to duplicate this behavior. Based on your descriptions, it sounds like you have code (C# or XAML) throwing exceptions which would cause the navigation methods to not work. Double check all your logic and debug through every method.

    Tuesday, February 28, 2017 3:06 AM
  • User195916 posted

    @NMackay
    @BrianLagunas I created the repo, that has same navigation stack, and it works totally fine. So it says that something wrong with my part, but I double checked my code. Maybe I have no enough knowledge about what could break navigation events. Could it be an EventAggregator messages? May you give me some thoughts where I should search? Here is repo, if it is needed: https://cloud.mail.ru/public/Jd4b/YWWstosmq Thank you for helping me.

    Tuesday, February 28, 2017 10:19 AM
  • User195916 posted

    @NMackay @BrianLagunas I rebuild the solution and it worked except one condition. OnNavigatedTo doesn't work on FilterPage when it comes with "GoBackAsync" from PlacesFilterPage on iOS. It is very strange actually. I like a fool in this situation.

    Also observed that OnNavigatedFrom works on Android but on iOS only when it comes from SpecialtyFilterPage.

    Tuesday, February 28, 2017 11:01 AM
  • User76049 posted

    @YuraBabiy

    I can't see anything causing issues in the repo, could you create a repo with the issue?

    What I would suggest is seeing what the task is returning, put a breakpoint there and see what's happening.

    var res = _navigationService.GoBackAsync....

    See if the task has faulted and if there's an exception.

    Not sure what else to suggest.

    Tuesday, February 28, 2017 12:16 PM
  • User195916 posted

    @NMackay I completely don't know what is happening. It changes its behavior all the time. Works - not, Android - iOS. Bad dream. About repo, I said that there are no issues and I can't repro something that has because I have no idea with what can cause something like this. I was trying to catch some exception but there is no one. All tasks are RanToCompletion and Exceptions = null. I just can't handle this issue. There is something new, is sometimes when it navigates from PlacesFilterPage or SpecialtyFilterPage with GoBackAsync, it does white display and doesn't navigate with a first try and only toolbar items visible and enable. On the second tap on software back-button, it navigates back and also does white display. And on third tap it's behavior is normal. It is only on iOS simulator. All time I was testing on iOS simulators and Android device and simulators.

    Tuesday, February 28, 2017 1:49 PM
  • User116727 posted

    @YuraBabiy you definitely have something weird going on with your app. All I can suggest is that you comment out all your code and all your XAML until it works. Then start slowing adding your XAML back, then start slowly adding your code back and see what breaks it.

    Tuesday, February 28, 2017 1:53 PM
  • User195916 posted

    @BrianLagunas Is it an expected behavior that OnNavigatingTo never fires when GoBackAsync?

    Tuesday, February 28, 2017 7:31 PM
  • User195916 posted

    @BrianLagunas I did a typo. I meant not GoBackAsync, but software and hardware back-button. When it pressed then only OnNavigatedTo and OnNavigatedFrom fires. Is it expected?

    Wednesday, March 1, 2017 7:57 AM
  • User195916 posted

    @NMackay @BrianLagunas So, Brian, I tried your suggestion and it was bloody hell. But it worked. I was successful to find which line exactly causes the problem and I made sample project. Here is the sample: https://cloud.mail.ru/public/5vQZ/gSUbM2D28 From my observation: The problem is because of this line in CustomSpannableLabel.cs in an iOS project: var fontFamily = Element.FontFamily; I have no idea why it can be, but it causes two problems: 1) If you press a soft back button, then you have nothing in fires; 2) If you press "Back" it fires only OnNavigatingTo and sometimes has a bug with a display, is when you have it white and not navigated. All this you can see when you on page B. On other pages it can to not have a bug even when you use CustomSpannableLabel on them, I have no idea why. It only occurs on iOS. On an Android, all works fine. (If my previous answer of comment is yes) Please, keep me posted. Maybe it is not about Prism, but still, I need help, your observation of this situation is very appreciated.

    Wednesday, March 1, 2017 2:12 PM
  • User76049 posted

    @YuraBabiy

    I'm having a look at this.

    Wednesday, March 1, 2017 2:28 PM
  • User76049 posted

    @YuraBabiy @BrianLagunas

    Your issue is the custom renderer, you always set the font even when the uielement is been destroyed when the page is been popped of the navigation stack.

    Old code

    protected override void OnElementChanged(ElementChangedEventArgs<Label> e) { base.OnElementChanged(e); UpdateFormattedText(); }

    New code

    ``` protected override void OnElementChanged(ElementChangedEventArgs

            if (e.OldElement != null)
            {
                // unhook event handlers etc here
            }
    
            if (e.NewElement != null)
            {
                UpdateFormattedText();
            }
        }
    

    ```

    I stuck some debug statements in the filter viewmodel and BPage viewmodel to check the GoBackAsync was successfull.

    ```

            var res = await _navigationService.GoBackAsync(parameters);
            Debug.WriteLine("BPageViewModel GoBackAsync was successful: " + res.ToString());
    

    ```

    With the old renderer:

    [0:] BPageViewModel: OnNavigatingTo [0:] Filter OnNavigatedFrom [0:] BPageViewModel: OnNavigatedTo [0:] Filter OnNavigatingTo [0:] BPageViewModel GoBackAsync was successful: False [0:] BPageViewModel: OnNavigatingTo [0:] Filter OnNavigatedFrom [0:] BPageViewModel: OnNavigatedTo

    With the fixed renderer:

    [0:] BPageViewModel: OnNavigatingTo [0:] Filter OnNavigatedFrom [0:] BPageViewModel: OnNavigatedTo [0:] Filter OnNavigatingTo [0:] BPageViewModel: OnNavigatedFrom [0:] Filter OnNavigatedTo Thread started: #6 [0:] BPageViewModel GoBackAsync was successful: True Thread started: <Thread Pool> #7 Thread started: <Thread Pool> #8 [0:] BPageViewModel: OnNavigatingTo [0:] Filter OnNavigatedFrom [0:] BPageViewModel: OnNavigatedTo [0:] BPageViewModel: OnNavigatedFrom [0:] Filter OnNavigatedTo Thread finished: <Thread Pool> #8 The thread 'Unknown' (0x8) has exited with code 0 (0x0).

    In both test I did the following

    Navigate to Page B Navigate back via view button Navigate to Page B Navigate back via soft back button

    OnNavigatingTo to doesn't seem to get called if you do a software back (I think that's a Forms limitation), but the issue is due to your renderer causing the page to probably remain in memory.

    • Marked as answer by Anonymous Thursday, June 3, 2021 12:00 AM
    Wednesday, March 1, 2017 2:52 PM
  • User195916 posted

    @NMackay It was just wow. I spent so much time. Good lesson for me. Thank you very much. Please repost answer on StackOverflow. It is not good for me to write an answer instead of you. The link is in the question above. And can you please explain me this thing about an old and new element? I mean, why there are old and new? Or maybe you know some source, where I can read it? Thank you again.

    Wednesday, March 1, 2017 3:13 PM
  • User76049 posted

    @YuraBabiy

    @DavidDancy documents a great response here.

    https://forums.xamarin.com/discussion/66779/what-is-all-this-new-old-and-element-stuff-inside-a-custom-renderer

    Regarding SO, Dan is absolutely correct, it's probably better to ask for help either here or on SO but not both, I don't answer on SO, I tried to answer once and my answer got rejected...for missing a fullstop probably :smile:

    Wednesday, March 1, 2017 3:21 PM
  • User195916 posted

    @NMackay About SO, stand one's ground. As for me, missing full stop is exactly what I need in most answers from someone. Thanks for the link.

    Wednesday, March 1, 2017 3:50 PM
  • User76049 posted

    @YuraBabiy

    No problem. it's always a good feeling to get down to the bottom of a problem that's been driving you crazy.

    Wednesday, March 1, 2017 3:57 PM
  • User116727 posted

    @YuraBabiy OnNavigatingTo does not fire on hardware/software button presses. This is a limitation of XF. If I called both methods, then OnNavigatingTo and OnNavigated to would be called one after the other and provide no real benefit.

    Wednesday, March 1, 2017 8:21 PM