緒論
UWP開發中,Page是最常用的Control之一,通常情況下,在開發的application中,每一個頁面就是一個Page。有時候,為了開發整合度更高,UI表現更為一致的UI,開發者需要把UI控件和功能整合到一個頁面的子頁面中,子頁面擁有自己的UI表現和生命周期,這就需要在Page中嵌套Page來達到需要實現的效果。
一種實現方法
其實,實現嵌套頁面是一件很簡單的事情,我們知道,page都是通過Frame顯示和控制Navigation的,基於這點,就可以在主頁面(即最外層的頁面)中添加一個Frame,通過控制這個Frame來實現子Page的顯示和導航。
在xmal中添加Frame
<Frame x:Name="contentFrame" Grid.Row="1"/>
在code中實現子Page的navigation
contentFrame.Navigate(typeof(Page1));
為子Frame添加默認的Page
protected override void OnNavigatedTo(NavigationEventArgs e) { if (e.NavigationMode == NavigationMode.New) { contentFrame.Navigate(typeof(Page1)); } base.OnNavigatedTo(e); }
為back鍵添加Event
public MainPage() { this.InitializeComponent(); SystemNavigationManager.GetForCurrentView().BackRequested += PageBackRequested; } private void PageBackRequested(object sender, BackRequestedEventArgs e) { if (contentFrame == null) return; if (contentFrame.CanGoBack) { e.Handled = true; contentFrame.GoBack(); } }
一個例子
在這個例子中,外層的MainPage有一個漢堡鍵配合SplitView菜單實現內層Page的切換,back鍵用來實現contentFrame的Navigation。其中,Page1和Page2是嵌套在MainPage里面的兩個Page。
MainPage.xaml
<Page x:Class="NestedFrameExample.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:NestedFrameExample" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="*"/> </Grid.RowDefinitions> <Grid Height="48" VerticalAlignment="Top" Background="White"> <Button x:Name="hamburgerButton" Background="Transparent" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Left" Click="SplitViewToggle_Click"> <TextBlock Text="" FontFamily="{ThemeResource SymbolThemeFontFamily}"/> </Button> </Grid> <!-- 這個Frame用於顯示子Page頁面。 --> <Frame x:Name="contentFrame" Grid.Row="1"/> <SplitView x:Name="splitView" Grid.Row="1" IsPaneOpen="False" OpenPaneLength="300" CompactPaneLength="48" DisplayMode="Overlay" HorizontalContentAlignment="Stretch"> <SplitView.Pane> <ListView ItemsSource="{x:Bind Path=NavLinks}" IsItemClickEnabled="True" ItemClick="NavLinkClick" SelectionMode="None"/> </SplitView.Pane> </SplitView> </Grid> </Page>
MainPage.xaml.cs
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.InteropServices.WindowsRuntime; using Windows.Foundation; using Windows.Foundation.Collections; using Windows.UI.Core; using Windows.UI.Xaml; using Windows.UI.Xaml.Controls; using Windows.UI.Xaml.Controls.Primitives; using Windows.UI.Xaml.Data; using Windows.UI.Xaml.Input; using Windows.UI.Xaml.Media; using Windows.UI.Xaml.Navigation; // The Blank Page item template is documented at http://go.microsoft.com/fwlink/?LinkId=402352&clcid=0x409 namespace NestedFrameExample { /// <summary> /// An empty page that can be used on its own or navigated to within a Frame. /// </summary> public sealed partial class MainPage : Page { public List<NavLink> NavLinks = new List<NavLink>() { new NavLink() { Label = "Page1", LinkType = typeof(Page1) }, new NavLink() { Label = "Page2", LinkType = typeof(Page2) } }; public MainPage() { this.InitializeComponent(); SystemNavigationManager.GetForCurrentView().AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible; SystemNavigationManager.GetForCurrentView().BackRequested += PageBackRequested; } private void NavLinkClick(object sender, ItemClickEventArgs e) { NavLink link = e.ClickedItem as NavLink; if (link != null && link.LinkType != null) contentFrame.Navigate(link.LinkType); splitView.IsPaneOpen = false; } private void SplitViewToggle_Click(object sender, RoutedEventArgs e) { splitView.IsPaneOpen = !splitView.IsPaneOpen; } protected override void OnNavigatedTo(NavigationEventArgs e) { //this.InitialBackButton(); if (e.NavigationMode == NavigationMode.New) { contentFrame.Navigate(typeof(Page1)); } base.OnNavigatedTo(e); } private void PageBackRequested(object sender, BackRequestedEventArgs e) { if (contentFrame == null) return; if (contentFrame.CanGoBack) { e.Handled = true; contentFrame.GoBack(); } } } public class NavLink { public String Label { get; set; } public Type LinkType { get; set; } public override String ToString() { return Label; } } }
總結
嵌套式的頁面使每個Page的結構更加清晰,更能專注於自己的功能實現,也使代碼更加清晰,容易維護,避免代碼冗余,推薦使用,希望本文能給大家帶來幫助!!