WPF之导航和Page的生命周期
如果Page1成功导航到Page2,首先会触发NavigationService的Navigating事件,标识导航开始。随后创建Page2对象,并且触发NavigationProgress事件。该事件用于提供导航进度信息,每次返回1KB数据就会引发该事件。随后触发Navigated事件,LoadCompleted紧随其后,这时表明页面已经下载完毕。Page1触发UnLoaded事件,宣告其结束。Page2触发Loaded事件,表明其开始。
上图表示了从Page1成功导航到Page2页面经过的完整事件。
第二张图表明了在同一个页面中从一个段落导航到另一个段落的过程。除去触发Navigating、Navigated和LoadCompleted事件以外,还触发FramentNavigation事件。
如果导航失败,如从Page1导航到了不存在的Page3,则触发NavigationFailed表示失败。可以在该事件处理函数中将传递过来的NavigationFailedEventargs的Handled
属性设置为True,从而防止异常而导致一个未处理的应用程序异常。
在APP中添加对各个事件的处理:
<Application x:Class="WpfApplication5.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Navigating="Application_Navigating_1" NavigationFailed="Application_NavigationFailed_1" Navigated="Application_Navigated_1" NavigationProgress="Application_NavigationProgress_1" NavigationStopped="Application_NavigationStopped_1" LoadCompleted="Application_LoadCompleted_1" FragmentNavigation="Application_FragmentNavigation_1" StartupUri="Page1.xaml"> <Application.Resources> </Application.Resources> </Application>
后台处理如下:
private void Application_NavigationFailed_1(object sender, System.Windows.Navigation.NavigationFailedEventArgs e) { System.Console.WriteLine("------------------------------------------"); System.Console.Write("触发的事件为:Application_NavigationFailed\n"); System.Console.WriteLine("失败的异常是: " + e.Exception.ToString()); // Handled属性设置为true,从而防止异常继续上传转变为一个未处理的应用程序异常 e.Handled = true; } private void Application_Navigated_1(object sender, System.Windows.Navigation.NavigationEventArgs e) { System.Console.WriteLine("------------------------------------------"); System.Console.Write("触发的事件为:Application_Navigated\n"); System.Console.WriteLine("导航页面的Uri:" + e.Uri.ToString()); } private void Application_NavigationProgress_1(object sender, System.Windows.Navigation.NavigationProgressEventArgs e) { System.Console.WriteLine("------------------------------------------"); System.Console.Write("触发的事件为:Application_NavigationProgress\n"); System.Console.WriteLine("导航页面的Uri:" + e.Uri.ToString()); System.Console.WriteLine("已经得到的字节数为{0}", e.BytesRead); } private void Application_NavigationStopped_1(object sender, System.Windows.Navigation.NavigationEventArgs e) { System.Console.WriteLine("------------------------------------------"); System.Console.Write("触发的事件为:Application_NavigationStopped\n"); System.Console.WriteLine("导航页面的Uri:" + e.Uri.ToString()); } private void Application_LoadCompleted_1(object sender, System.Windows.Navigation.NavigationEventArgs e) { System.Console.WriteLine("------------------------------------------"); System.Console.Write("触发的事件为:Application_LoadCompleted\n"); System.Console.WriteLine("导航页面的Uri:" + e.Uri.ToString()); } private void Application_FragmentNavigation_1(object sender, System.Windows.Navigation.FragmentNavigationEventArgs e) { System.Console.WriteLine("------------------------------------------"); System.Console.Write("触发的事件为:Application_FragmentNavigation\n"); System.Console.WriteLine("导航的段落为:" + e.Fragment); } private void Application_Navigating_1(object sender, System.Windows.Navigation.NavigatingCancelEventArgs e) { System.Console.WriteLine("------------------------------------------"); System.Console.Write("触发的事件为:Application_Navigating\n"); System.Console.WriteLine("导航页面的Uri:" + e.Uri.ToString()); }
运行一个测试页面跳转一下试试看,会看到跳转背后详细的过程。
<Page x:Class="WpfApplication5.Page1" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Page1" Loaded="Page_Loaded" Unloaded="Page_Unloaded"> <StackPanel> <TextBlock> 从Page1导航到 <Hyperlink NavigateUri="Page2.xaml"> Page2.xaml </Hyperlink> </TextBlock> <TextBlock> 从Page1导航到 <Hyperlink NavigateUri="Page3.xaml"> 一个不存在的网页 </Hyperlink> </TextBlock> <TextBlock> 从Page1导航到 <Hyperlink Click="Hyperlink_Click"> Page2.xaml </Hyperlink> 但是随即会取消 </TextBlock> <TextBlock> <Hyperlink Click="Hyperlink_Click_1"> 刷新 </Hyperlink> 当前页面 </TextBlock> </StackPanel> </Page>
public partial class Page1 : Page { public Page1() { System.Console.WriteLine("------------------------------------------"); System.Console.WriteLine("Page1 被创建出来"); InitializeComponent(); } private void Hyperlink_Click(object sender, RoutedEventArgs e) { NavigationService.Navigate(new Uri("pack://application:,,,/Page2.xaml")); Thread.Sleep(500); NavigationService.StopLoading(); } private void Hyperlink_Click_1(object sender, RoutedEventArgs e) { NavigationService.Refresh(); } private void Page_Loaded(object sender, RoutedEventArgs e) { System.Console.WriteLine("------------------------------------------"); System.Console.WriteLine("Page1 Loaded"); } private void Page_Unloaded(object sender, RoutedEventArgs e) { System.Console.WriteLine("------------------------------------------"); System.Console.WriteLine("Page1 UnLoaded"); } void NavigationService_Navigating(object sender, NavigatingCancelEventArgs e) { MessageBoxResult result; result = MessageBox.Show("是否要离开当前页面", "提示", MessageBoxButton.YesNo); if (result == MessageBoxResult.No) e.Cancel = true; }
上述的代码中有跳转存在的页面和不存在的页面,同时也拥有刷新的功能以及在跳转页面之前进行跳转提示。