Do code after OnNavigatedTo

2020-04-21 04:25发布

问题:

I Have Code get IdUsers From Other Page

String IdUsers;

        public Main_Wallets_Page()
        {
            InitializeComponent();            
            MessageBox.Show(IdUsers);
        }


protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
        {
            String Id;
            if (NavigationContext.QueryString.TryGetValue("IdUsers", out Id))
                IdUsers = Id;
        }

The MessageBox Alway be Null. I Want to MessageBox Show the "IdUsers" after OnNavigationTo (Do not put the MessageBox IN "OnNavigationTo").

How can i do it ?

回答1:

You shouldn't use MessageBoxes in OnNavigatedTo because if the user does not press a button your app will crash since the framework thinks that navigation has failed. MessageBoxes in the constructor are equally as bad.

I can think of two options (I use #1 for these sorts of things):

  1. Show the MessageBox in the Loaded event. But be careful it can be fired more than once. In the constructor you might add the handler for the Loaded event and then in the handler you'd detach from the handler so that it is called only once.

  2. Use Dispatcher.BeginInvoke around the MessageBox.Show call so that it does not block navigation. That might still block the Dispatcher thread. If you really wanted to go this route you could use ThreadPool.QueueUserWorkItem or a TPL Task.

I also have used OnLayoutUpdated in place of the Loaded event but I can't remember exactly why :) It seems like it might have been that the page hasn't yet displayed in Loaded and it has in the other event.



回答2:

If this value was initialized, you can store it in application isolated storage. Then, when constructor is called, you can read it from there. In this case value of user ID will be initialized and MessageBox won't show you NULL.



回答3:

DO NOT place MessageBox into OnNavigatedTo event. Try to create an empty project with MainPage and Page2. Place button on MainPage to navigate to Page2. In Page2 place MessageBox in OnNavigatedTo event. Then everythig will work fine if you Start Debugging from VS. BUT if you deploy and run it you will see that when you navigate to Page2 you see MessageBox. Then don't do anything, just wait for about 15 sec. MessageBox will react as Canceled and APPLICATION WILL BE CRASHED! without any navigation to Page2 or MainPage. The same thing happens if you use Dispatcher.BeginInvoke around the MessageBox.Show. I assume that OnNavigatedTo event has a timeout which works only when app is deployed. So you should run your MessageBox when Navigation is competed. Everything works if you do

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) {
    base.OnNavigatedTo(e);

    var lcTimer = new DispatcherTimer { Interval = new TimeSpan(0, 0, 0, 0, 200) };
    lcTimer.Tick += (s2, e2) => {
         (s2 as DispatcherTimer).Stop();
         if (MessageBoxResult.OK == MessageBox.Show("Test, don't push", "", MessageBoxButton.OKCancel))
             MessageBox.Show("OK");
         else
             MessageBox.Show("Cancel");
    };
    lcTimer.Start();
}

Note: If you have some code in OnNavigatedTo run above code at the end of OnNavigatedTo.

I liked what Austin Thompson(upvote) has adviced with ThreadPool.QueueUserWorkItem. But note that with this approach you need to place MessageBox inside the Dispatcher.BeginInvoke otherwise you will receive cross-thread exception. So the code is the following

protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e) {
    base.OnNavigatedTo(e);

    ThreadPool.QueueUserWorkItem((stateInfo) => {
        Dispatcher.BeginInvoke(() => {
            if (MessageBoxResult.OK == MessageBox.Show("Test don't push", "", MessageBoxButton.OKCancel))
                MessageBox.Show("OK");
            else
                MessageBox.Show("Cancel");
        });
    });
}