Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xamarin Forms - Prism - OnNavigatedTo Calling Twice

So, I've been developing an App for 2 months with prism, and just now I've realized that the method OnNavigatedTo is been calling twice when I select an Item from a MasterDetailPage.

I have no clue why it is happening, I'm sure I'm missing something but I'm about two days trying to solve it.

I'll put some code here, and if u guys need more info I can post more detailed.

Observation: When I'm in the page "A" and I choose the page "A" in the master detail item list, the OnNavigatedTo is called only once, but when I'm in Page "B" and I choose the page "A", The OnNavigatedTo is called twice.

Since now, Thank you guys and sorry about the ignorance.

MasterDetailPage MVVM:

public class PrincipalMasterDetailPageViewModel : ViewModelBase {
        public ObservableCollection<PrincipalMasterPageItem> MenuItems { get; set; }

        public PrincipalMasterDetailPageViewModel(INavigationService navigationService) : base(navigationService)
        {
            MenuItems = new ObservableCollection<PrincipalMasterPageItem>();
        }
        public async override void OnNavigatedTo(NavigationParameters parameters) {
            base.OnNavigatedTo(parameters);
            .. Here I'm calling an API, thats why I have the async
        }
    }

Custom Navigation Page MVVM:

public class PrincipalNavigationPageViewModel : ViewModelBase {
        public PrincipalNavigationPageViewModel(INavigationService navigationService) : base(navigationService) {
        }
    }

The Page that I actually show when I select an item in masterdetailpage item list:

public class NewPageTestViewModel : ViewModelBase
    {
        public NewPageTestViewModel(INavigationService navigationService) : base(navigationService)
        {

        }

        public override void OnNavigatedTo(NavigationParameters parameters)
        {
            base.OnNavigatedTo(parameters);
            Debug.WriteLine("Calling twice HERE!");
        }
    }

The RegisterTypes of these three examples:

    containerRegistry.RegisterForNavigation<PrincipalMasterDetailPage>();
containerRegistry.RegisterForNavigation<PrincipalNavigationPage>();
containerRegistry.RegisterForNavigation<NewPageTest>();

How do I call other pages from PrincipalMasterDetailPageViewModel:

NavigationService.NavigateAsync(string.Format("PrincipalNavigationPage/{0}", item.TargetPageName));

In App.cs I start like the following because I need the login page first:

protected override async void OnInitialized()
        {
            InitializeComponent();

            await NavigationService.NavigateAsync("LoginPage");
        }

When the user log in, It navigate like this:

await NavigationService.NavigateAsync("/PrincipalMasterDetailPage/PrincipalNavigationPage/WhateverPageIWantTo");
like image 858
Marcio E. H Avatar asked Oct 12 '25 18:10

Marcio E. H


1 Answers

I don't know if anybody is still interested in this but I ran into the same issue and figured out what is going on.

All code samples I found register a NavigationPage like this:

containerRegistry.RegisterForNavigation<NavigationPage>("Navigation");

In order to be able to do something like this on app launch:

 NavigationService.NavigateAsync($"Main/Navigation/Home");

However, the problem seems to be that when this NavigationPage is instantiated without a specific ViewModel assinged to it, the 'INavigationAware' events are somehow propagated to the MasterDetailPage's ViewModel resulting in the events on that one to be called twice.

I fixed it by registering the NavigationPage for Navigation with a ViewModel like this:

    containerRegistry.RegisterForNavigation<NavigationPage, NavigationPageViewModel>("Navigation");

The ViewModel itself is nothing special:

using Prism.Commands;
using Prism.Mvvm;
using Prism.Navigation;
using System;
using System.Collections.Generic;
using System.Linq;
using Unity.Attributes;

namespace SocialRecipe.ViewModels
{
    public class NavigationPageViewModel : ViewModelBase
    {
        public NavigationPageViewModel()
        {

        }

        public override void OnNavigatedFrom(INavigationParameters parameters)
        {
        }

        public override void OnNavigatedTo(INavigationParameters parameters)
        {
        }

        public override void OnNavigatingTo(INavigationParameters parameters)
        {
        }
    }
}

This way the events of the NavigationPage are routed to the NavigationPageViewModel and are no longer propagated to the MasterDetailPage…