如何在WinUI 3中实现局部区域显示的欢迎导航屏幕
解决WinUI 3局部区域页面导航的问题
问题概述
我正在用WinUI 3开发欢迎屏幕,需求如下:
- 点击返回、下一步按钮,可在3个页面间导航;
- 页面内容仅显示在主窗口水平线以上的区域;
- 通过三个圆点标识总页数和当前页面。
官方导航示例是用整个窗口做导航,我需要修改成仅在指定局部区域显示导航页面,现有代码如下:
现有代码
MainWindow.xaml
<?xml version="1.0" encoding="utf-8"?> <Window x:Class="BasicNavigation.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:BasicNavigation" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" > <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" VerticalAlignment="Center" > </StackPanel> </Window>
App.xaml.cs
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) { m_window = new MainWindow(); // Create a Frame to act as the navigation context and navigate to the first page Frame rootFrame = new Frame(); rootFrame.NavigationFailed += OnNavigationFailed; // Navigate to the first page, configuring the new page // by passing required information as a navigation parameter rootFrame.Navigate(typeof(MainPage), args.Arguments); // Place the frame in the current Window m_window.Content = rootFrame; // Ensure the MainWindow is active m_window.Activate(); } void OnNavigationFailed(object sender, NavigationFailedEventArgs e) { throw new Exception("Failed to load Page " + e.SourcePageType.FullName); }
解决方案
核心思路是不要把Frame设为窗口的整个Content,而是将Frame嵌入到MainWindow的指定布局区域内,同时保留导航逻辑。以下是具体修改步骤:
1. 修改MainWindow.xaml,规划局部导航区域
在窗口中划分出导航内容区、控制按钮区和页码指示器,示例布局如下:
<?xml version="1.0" encoding="utf-8"?> <Window x:Class="BasicNavigation.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:BasicNavigation" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Width="800" Height="600" > <Grid> <!-- 水平线以上的导航内容区 --> <Frame x:Name="NavigationFrame" Margin="20" Height="350" VerticalAlignment="Top"/> <!-- 分隔线 --> <Rectangle Fill="Gray" Height="1" VerticalAlignment="Center"/> <!-- 底部控制区:返回/下一步按钮 + 页码圆点 --> <StackPanel Orientation="Vertical" VerticalAlignment="Bottom" Margin="0 20 0 20"> <!-- 按钮栏 --> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Spacing="20"> <Button x:Name="BackButton" Content="返回" Click="BackButton_Click" IsEnabled="False"/> <Button x:Name="NextButton" Content="下一步" Click="NextButton_Click"/> </StackPanel> <!-- 页码指示器 --> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0 15 0 0" Spacing="8"> <Ellipse x:Name="Dot1" Fill="Blue" Width="12" Height="12"/> <Ellipse x:Name="Dot2" Fill="LightGray" Width="12" Height="12"/> <Ellipse x:Name="Dot3" Fill="LightGray" Width="12" Height="12"/> </StackPanel> </StackPanel> </Grid> </Window>
2. 修改App.xaml.cs,初始化局部Frame
不再把Frame设为窗口Content,而是直接在MainWindow加载时初始化内部的NavigationFrame:
protected override void OnLaunched(Microsoft.UI.Xaml.LaunchActivatedEventArgs args) { m_window = new MainWindow(); // 获取窗口内的导航Frame Frame navFrame = (m_window as MainWindow).NavigationFrame; navFrame.NavigationFailed += OnNavigationFailed; // 导航到第一个页面 navFrame.Navigate(typeof(WelcomePage1), args.Arguments); m_window.Activate(); } void OnNavigationFailed(object sender, NavigationFailedEventArgs e) { throw new Exception("Failed to load Page " + e.SourcePageType.FullName); }
3. 实现导航逻辑和页码更新
在MainWindow.xaml.cs中添加按钮点击事件和导航状态监听:
using Microsoft.UI.Xaml.Controls; using Microsoft.UI.Xaml.Navigation; namespace BasicNavigation { public sealed partial class MainWindow : Window { public MainWindow() { this.InitializeComponent(); // 监听导航事件,更新按钮状态和页码圆点 NavigationFrame.Navigated += NavigationFrame_Navigated; } private void BackButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) { if (NavigationFrame.CanGoBack) { NavigationFrame.GoBack(); } } private void NextButton_Click(object sender, Microsoft.UI.Xaml.RoutedEventArgs e) { // 根据当前页面判断下一步导航目标 if (NavigationFrame.Content is WelcomePage1) { NavigationFrame.Navigate(typeof(WelcomePage2)); } else if (NavigationFrame.Content is WelcomePage2) { NavigationFrame.Navigate(typeof(WelcomePage3)); } // 如果是最后一页,可以添加完成逻辑 } private void NavigationFrame_Navigated(object sender, NavigationEventArgs e) { // 更新返回按钮状态 BackButton.IsEnabled = NavigationFrame.CanGoBack; // 更新页码圆点 Dot1.Fill = new Microsoft.UI.Xaml.Media.SolidColorBrush(Microsoft.UI.Colors.LightGray); Dot2.Fill = new Microsoft.UI.Xaml.Media.SolidColorBrush(Microsoft.UI.Colors.LightGray); Dot3.Fill = new Microsoft.UI.Xaml.Media.SolidColorBrush(Microsoft.UI.Colors.LightGray); if (e.SourcePageType == typeof(WelcomePage1)) { Dot1.Fill = new Microsoft.UI.Xaml.Media.SolidColorBrush(Microsoft.UI.Colors.Blue); NextButton.Content = "下一步"; } else if (e.SourcePageType == typeof(WelcomePage2)) { Dot2.Fill = new Microsoft.UI.Xaml.Media.SolidColorBrush(Microsoft.UI.Colors.Blue); NextButton.Content = "下一步"; } else if (e.SourcePageType == typeof(WelcomePage3)) { Dot3.Fill = new Microsoft.UI.Xaml.Media.SolidColorBrush(Microsoft.UI.Colors.Blue); NextButton.Content = "完成"; } } } }
4. 创建欢迎页面(示例)
分别创建WelcomePage1.xaml、WelcomePage2.xaml、WelcomePage3.xaml,每个页面只需添加简单内容即可,比如:
<!-- WelcomePage1.xaml --> <Page x:Class="BasicNavigation.WelcomePage1" 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" mc:Ignorable="d" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}" > <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock Text="欢迎页面1" FontSize="24"/> </StackPanel> </Page>
关键说明
- 导航Frame是嵌入在MainWindow的Grid布局中的,仅占据顶部指定区域,不会覆盖整个窗口;
- 通过监听Frame的
Navigated事件,实时更新返回按钮状态和页码指示器的圆点颜色; - 下一步按钮的逻辑可以根据实际需求调整,比如最后一页改为"完成"并执行结束流程。
内容的提问来源于stack exchange,提问作者Ming
相关产品推荐
相关产品推荐

