Page

Page 是 WPF 中专为导航场景设计的轻量级内容容器,不能独立显示,必须放在 FrameNavigationWindow 中,类似网页的 “页面”,支持前进 / 后退、生命周期、页面缓存与数据传递。

一、核心概念与定位

1. 本质与继承

  • 继承链:Page → ContentControl → Control → FrameworkElement
  • 本质:内容控件,只能有一个直接子元素(通常用 Grid/StackPanel 包裹)
  • 核心定位:导航单元,用于构建多页式、向导式、浏览器式界面

2. 与 Window / UserControl 对比(关键区别)

特性WindowPageUserControl
独立运行 ✅ 可直接启动 ❌ 必须依赖 Frame/NavigationWindow ❌ 需嵌入容器
窗口边框 ✅ 自带标题栏 / 边框 ❌ 无任何窗口装饰 ❌ 无
导航支持 ❌ 无内置导航 ✅ 内置 NavigationService、前进 / 后退栈 ❌ 无
生命周期 Loaded/Closing/Closed OnNavigatedTo/From、Navigating Loaded/Unloaded
适用场景 主窗口、独立弹窗 多页导航、向导、内容浏览 复用 UI 模块、局部组件

 

3. 必须的宿主容器

Page 不能单独显示,必须放在以下两种容器中:
  1. Frame:最常用,可嵌入 Window/UserControl/Page 任意位置,支持局部导航
  2. NavigationWindow:自带导航栏(前进 / 后退)的顶层窗口,适合全屏导航应用

二、Page 常用属性

属性作用常用值
Title 页面标题(可同步到宿主窗口标题) 字符串
Background 页面背景 颜色 / 画刷
FontFamily/FontSize 页面默认字体 系统字体 / 数值
NavigationService 导航服务(只读,用于代码导航) NavigationService 对象
KeepAlive 是否在导航历史中保留实例(缓存) True/False(默认 False)
ShowsNavigationUI 是否显示宿主的导航 UI(前进 / 后退) True/False

 

三、Page 核心生命周期(导航事件)

Page 有专属的导航生命周期,比 Window 更精细:
  1. Navigating:导航开始前触发(可拦截跳转)
  2. Navigated:导航完成后触发(页面已加载)
  3. LoadCompleted:页面内容完全加载后触发
  4. OnNavigatedTo:页面被导航到时触发(初始化数据首选)
  5. OnNavigatedFrom:页面被导航离开时触发(保存数据)
  6. Unloaded:页面卸载时触发

四、导航核心:NavigationService

每个 Page 都有 NavigationService 属性,用于代码控制导航:
  • Navigate(Page/Uri):跳转到指定页面
  • GoBack():后退(需判断 CanGoBack
  • GoForward():前进(需判断 CanGoForward
  • Journal:导航历史栈(前进 / 后退记录)
  • StopLoading():停止加载
  • Refresh():刷新当前页面

五、完整实战示例(Frame + 多 Page 导航)

步骤 1:创建 WPF 项目

新建 WPF 应用,添加 3 个 Page:HomePage.xamlPage1.xamlPage2.xaml

示例 1:主窗口(含 Frame 容器)

 1 <!-- MainWindow.xaml -->
 2 <Window x:Class="WpfPageDemo.MainWindow"
 3         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 4         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 5         Title="WPF Page 导航演示" Height="600" Width="800"
 6         WindowStartupLocation="CenterScreen">
 7     <Grid>
 8         <!-- 顶部导航栏 -->
 9         <StackPanel Orientation="Horizontal" VerticalAlignment="Top" Background="#f0f0f0" Padding="10">
10             <Button Content="首页" Click="BtnHome_Click" Margin="5"/>
11             <Button Content="页面1" Click="BtnPage1_Click" Margin="5"/>
12             <Button Content="页面2" Click="BtnPage2_Click" Margin="5"/>
13             <Button Content="后退" Click="BtnBack_Click" Margin="5"/>
14             <Button Content="前进" Click="BtnForward_Click" Margin="5"/>
15         </StackPanel>
16 
17         <!-- Frame 容器:承载所有 Page -->
18         <Frame x:Name="MainFrame" 
19                Margin="0,60,0,0" 
20                NavigationUIVisibility="Hidden"  <!-- 隐藏默认导航栏 -->
21                Background="White"/>
22     </Grid>
23 </Window>
 1 // MainWindow.xaml.cs
 2 using System;
 3 using System.Windows;
 4 using WpfPageDemo.Pages;
 5 
 6 namespace WpfPageDemo
 7 {
 8     public partial class MainWindow : Window
 9     {
10         public MainWindow()
11         {
12             InitializeComponent();
13             // 初始加载首页
14             MainFrame.Navigate(new HomePage());
15         }
16 
17         // 导航到首页
18         private void BtnHome_Click(object sender, RoutedEventArgs e)
19         {
20             MainFrame.Navigate(new HomePage());
21         }
22 
23         // 导航到页面1
24         private void BtnPage1_Click(object sender, RoutedEventArgs e)
25         {
26             MainFrame.Navigate(new Page1());
27         }
28 
29         // 导航到页面2
30         private void BtnPage2_Click(object sender, RoutedEventArgs e)
31         {
32             MainFrame.Navigate(new Page2());
33         }
34 
35         // 后退
36         private void BtnBack_Click(object sender, RoutedEventArgs e)
37         {
38             if (MainFrame.CanGoBack) MainFrame.GoBack();
39         }
40 
41         // 前进
42         private void BtnForward_Click(object sender, RoutedEventArgs e)
43         {
44             if (MainFrame.CanGoForward) MainFrame.GoForward();
45         }
46     }
47 }

示例 2:首页 Page(HomePage.xaml)

 1 <Page x:Class="WpfPageDemo.Pages.HomePage"
 2       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4       Title="首页"
 5       KeepAlive="True">  <!-- 缓存页面实例,导航回来不重新创建 -->
 6     <Grid Background="LightBlue">
 7         <TextBlock Text="这是首页" FontSize="30" 
 8                    HorizontalAlignment="Center" VerticalAlignment="Center"/>
 9         <Button Content="跳转到页面1" Click="BtnGoPage1_Click"
10                 Width="150" Height="40" VerticalAlignment="Bottom" Margin="20"/>
11     </Grid>
12 </Page>
 1 // HomePage.xaml.cs
 2 using System.Windows;
 3 using System.Windows.Controls;
 4 
 5 namespace WpfPageDemo.Pages
 6 {
 7     public partial class HomePage : Page
 8     {
 9         public HomePage()
10         {
11             InitializeComponent();
12         }
13 
14         // 页面内导航到 Page1
15         private void BtnGoPage1_Click(object sender, RoutedEventArgs e)
16         {
17             this.NavigationService.Navigate(new Page1());
18         }
19 
20         // 页面被导航到(初始化)
21         protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
22         {
23             base.OnNavigatedTo(e);
24             MessageBox.Show("进入首页!");
25         }
26 
27         // 页面被导航离开(保存数据)
28         protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
29         {
30             base.OnNavigatedFrom(e);
31             MessageBox.Show("离开首页!");
32         }
33     }
34 }

示例 3:页面 1(Page1.xaml,含拦截导航)

 1 <Page x:Class="WpfPageDemo.Pages.Page1"
 2       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 3       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 4       Title="页面1">
 5     <Grid Background="LightGreen">
 6         <TextBlock Text="这是页面1" FontSize="30" 
 7                    HorizontalAlignment="Center" VerticalAlignment="Center"/>
 8         <Button Content="跳转到页面2" Click="BtnGoPage2_Click"
 9                 Width="150" Height="40" VerticalAlignment="Bottom" Margin="20"/>
10     </Grid>
11 </Page>
 1 // Page1.xaml.cs
 2 using System.Windows;
 3 using System.Windows.Controls;
 4 using System.Windows.Navigation;
 5 
 6 namespace WpfPageDemo.Pages
 7 {
 8     public partial class Page1 : Page
 9     {
10         public Page1()
11         {
12             InitializeComponent();
13             // 注册导航开始事件(可拦截)
14             this.NavigationService.Navigating += NavigationService_Navigating;
15         }
16 
17         private void BtnGoPage2_Click(object sender, RoutedEventArgs e)
18         {
19             this.NavigationService.Navigate(new Page2());
20         }
21 
22         // 导航开始前触发(可拦截跳转)
23         private void NavigationService_Navigating(object sender, NavigatingCancelEventArgs e)
24         {
25             MessageBoxResult result = MessageBox.Show("确定要离开页面1吗?", "提示", 
26                                                   MessageBoxButton.YesNo);
27             if (result == MessageBoxResult.No)
28             {
29                 e.Cancel = true; // 拦截导航,不跳转
30             }
31         }
32     }
33 }

示例 4:页面 2(Page2.xaml,最简单)

1 <Page x:Class="WpfPageDemo.Pages.Page2"
2       xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
3       xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
4       Title="页面2">
5     <Grid Background="LightCoral">
6         <TextBlock Text="这是页面2" FontSize="30" 
7                    HorizontalAlignment="Center" VerticalAlignment="Center"/>
8     </Grid>
9 </Page>

六、关键知识点详解

1. Page 内容限制

同 Window,只能有一个直接子元素,必须用布局容器包裹:
 1 <!-- 错误 -->
 2 <Page>
 3   <TextBlock/>
 4   <Button/>
 5 </Page>
 6 
 7 <!-- 正确 -->
 8 <Page>
 9   <Grid>
10     <TextBlock/>
11     <Button/>
12   </Grid>
13 </Page>

2. 导航的两种方式

(1)代码导航(最常用)

1 // 方式1:导航到 Page 实例
2 this.NavigationService.Navigate(new Page1());
3 
4 // 方式2:通过 URI 导航(XAML路径)
5 this.NavigationService.Navigate(new Uri("Pages/Page1.xaml", UriKind.Relative));
6 
7 // 方式3:Frame 直接导航
8 MainFrame.Navigate(new Page1());

(2)XAML 超链接导航

1 <Hyperlink NavigateUri="Pages/Page1.xaml">跳转到页面1</Hyperlink>

3. 页面缓存(KeepAlive)

  • KeepAlive="True":导航历史中保留 Page 实例,返回时不重新创建(状态保留)
  • KeepAlive="False"(默认):每次导航都创建新实例(适合无状态页面)

4. 页面间数据传递

(1)构造函数传值(推荐)

1 // 发送页
2 MainFrame.Navigate(new Page2("来自首页的数据"));
3 
4 // 接收页 Page2
5 public Page2(string data)
6 {
7     InitializeComponent();
8     txtData.Text = data;
9 }

(2)NavigationService 传值

1 // 发送
2 this.NavigationService.Navigate(new Page2(), "传递的数据");
3 
4 // 接收(OnNavigatedTo)
5 protected override void OnNavigatedTo(NavigationEventArgs e)
6 {
7     string data = e.ExtraData as string;
8 }

(3)全局变量 / ViewModel(MVVM 推荐)

5. NavigationWindow 使用(全屏导航)

1 <!-- NavigationWindow.xaml -->
2 <NavigationWindow x:Class="WpfPageDemo.MainNavWindow"
3                   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
4                   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
5                   Title="导航窗口" Height="600" Width="800"
6                   Source="Pages/HomePage.xaml"> <!-- 初始页面 -->
7 </NavigationWindow>
1 // App.xaml 修改启动窗口
2 StartupUri="MainNavWindow.xaml"

七、总结

  1. Page 是 WPF 导航专用的轻量级内容容器,必须依赖 Frame/NavigationWindow 显示
  2. 核心能力:导航历史、生命周期、页面缓存、数据传递
  3. 适用场景:多页应用、向导、设置界面、内容浏览、帮助系统
  4. 关键 API:NavigationService(导航控制)、OnNavigatedTo/From(生命周期)、KeepAlive(缓存)
posted on 2026-03-27 13:47  工业搬砖猿Lee  阅读(48)  评论(0)    收藏  举报