When is NavigationService initialized?

2019-02-25 10:19发布

问题:

I want to catch the NavigationService.Navigating event from my Page, to prevent the user from navigating forward. I have an event handler defined thusly:

void PreventForwardNavigation(object sender, NavigatingCancelEventArgs e)
{
    if (e.NavigationMode == NavigationMode.Forward)
    {
        e.Cancel = true;
    }
}

... and that works fine. However, I am unsure exactly where to place this code:

NavigationService.Navigating += PreventForwardNavigation;

If I place it in the constructor of the page, or the Initialized event handler, then NavigationService is still null and I get a NullReferenceException. However, if I place it in the Loaded event handler for the Page, then it is called every time the page is navigated to. If I understand right, that means I'm handling the same event multiple times.

Am I ok to add the same handler to the event multiple times (as would happen were I to use the page's Loaded event to hook it up)? If not, is there some place in between Initialized and Loaded where I can do this wiring?

回答1:

@Espo your link helped me find the workaround. I call it a workaround because it's ugly, but it's what MS themselves do in their documentation:

public MyPage() // ctor
{
    InitializeComponent();
    this.Loaded += delegate { NavigationService.Navigating += MyNavHandler; };
    this.Unloaded += delegate { NavigationService.Navigating -= MyNavHandler; };
}

So you basically have to unsubscribe from the navigation service's events when your page is unloaded.

+1 to your response for helping me find it. I don't seem to be able to mark my own response as the "accepted answer" so I guess I'll leave it for now.



回答2:

NavigationService.Navigate triggers both a NavigationService.Navigating event AND an Application.Navigating event. I solved this problem with the following:

public class PageBase : Page
{
    static PageBase()
    {
        Application.Current.Navigating += NavigationService_Navigating;
    }

    protected static void NavigationService_Navigating(object sender, NavigatingCancelEventArgs e)
    {
        // put your event handler code here...
    }
}