0

I'm trying to navigate to a Page after a user chooses "Yes" from a MessageBox that is displayed, but my Frame does not do the navigation until I display another MessageBox telling the user that the navigation has completed.

I've tried adding another Thread.Sleep(5000); and MessageBox after the "Success" MessageBox, (to see if the Frame only updates after the entire method completes) but the Frame will still navigate as soon as the "Success" MessageBox appears.

Here is my MainWindow.xaml:

<Window x:Class="WpfApp23.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApp23"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="10*" />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Frame x:Name="MyFrame" Content="" Margin="0" />
        <Button x:Name="MyButton" Content="Navigate" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center" Width="75" Click="MyButton_Click" Grid.Row="1" />
    </Grid>
</Window>

Here is my button click event handler from MainWindow.xaml.cs:

private void MyButton_Click(object sender, RoutedEventArgs e)
{
    MessageBoxResult messageBoxResult = MessageBox.Show("Navigate to page?", "Test", MessageBoxButton.YesNo);

    if (messageBoxResult == MessageBoxResult.Yes)
    {
        MyFrame.NavigationService.Navigate(new Uri("Test.xaml", UriKind.Relative));
        Thread.Sleep(5000); // Used to exaggerate time it takes to do other tasks.
        MessageBox.Show("Success");
    }
}

Test.xaml is just a dummy page that I've created that holds nothing but a label:

<Grid>
    <Label Content="Test Page" HorizontalAlignment="Center" Margin="0" VerticalAlignment="Center" />
</Grid>

I would like the Frame to navigate as soon as the user selected "Yes", so why is it waiting to navigate until the "Success" MessageBox appears?

fmcgarry
  • 92
  • 2
  • 9
  • 1
    You can't sleep, display a message box and navigate to a page simultaneously on the same thread. Do you want to display the MessageBox *after* the page has been navigated to or what are you trying to do? – mm8 Jan 04 '19 at 15:49
  • I mean, can't you just add MesssageBox.Show("Success") on Test.xaml.cs? – Adam McMahon Jan 04 '19 at 15:51
  • The page that I'm navigating to is just a filler page that displays to users while the application is waiting to complete certain tasks. What I originally had in mind would be a page that only displays "Saving - Please wait..." to the user while my application completes all of the saving. When saving is complete, another MessageBox appears notifying the user "Saving complete." and the returns to the previous page they were on. – fmcgarry Jan 04 '19 at 16:07

2 Answers2

1

You can't sleep, display a message box and navigate to a page simultaneously on the same thread.

If you want to display the MessageBox after the page has been navigated to, you could handle the Navigated event.

This event occurs when the content that is being navigated to has been found, and is available from Content property, although it may not have completed loading:

private void MyButton_Click(object sender, RoutedEventArgs e)
{
    MessageBoxResult messageBoxResult = MessageBox.Show("Navigate to page?", "Test", MessageBoxButton.YesNo);

    if (messageBoxResult == MessageBoxResult.Yes)
    {
        System.Windows.Navigation.NavigatedEventHandler handler = null;
        handler = async (ss, ee) =>
        {
            await Task.Delay(1000);
            MessageBox.Show("Success");
            MyFrame.Navigated -= handler;
        };
        MyFrame.Navigated += handler;
        MyFrame.NavigationService.Navigate(new Uri("Test.xaml", UriKind.Relative));
    }
}
mm8
  • 163,881
  • 10
  • 57
  • 88
  • I think this will work great for what I need to do, thanks! I just need to replace `Task.Delay(1000);` with a task that I've created that does all of the other things that I need to do while I'm displaying the Test page. – fmcgarry Jan 04 '19 at 16:26
-1

The problem that I was having was that my Frame was not updating until the "Success" MessageBox was shown. After searching for a while I was able to find an answer that mentions using a "hack" called Application.DoEvents().

But since I'm using WPF and not WinForms, there is no Application.DoEvents() method. Instead, you need to call

Application.Current.Dispatcher.Invoke(DispatcherPriority.Background, new Action(delegate { }));

After navigating to your page and before doing other tasks. Here is a link to the specific answer that I found.

fmcgarry
  • 92
  • 2
  • 9