NavigationWindow表示支持导航内容的窗体。虽然它继承于Window类型,但是,NavigationWindow不可以在XAML直接设置它的Content属性,不过可以在C#代码中实现。当然,这样做并没有什么太大的好处,因为既然它是用来做导航页面的,那么,我们应该发挥它最大的功效。
一、NavigationWindow的定义
public class NavigationWindow : Window, INavigator, INavigatorBase, INavigatorImpl, IDownloader, IJournalNavigationScopeHost, IUriContext
{
public static readonly DependencyProperty SandboxExternalContentProperty;
public static readonly DependencyProperty ShowsNavigationUIProperty;
public static readonly DependencyProperty BackStackProperty;
public static readonly DependencyProperty ForwardStackProperty;
public static readonly DependencyProperty CanGoBackProperty;
public static readonly DependencyProperty CanGoForwardProperty;
public static readonly DependencyProperty SourceProperty;
public NavigationWindow();
public IEnumerable BackStack { get; }
public IEnumerable ForwardStack { get; }
public bool ShowsNavigationUI { get; set; }
public Uri Source { get; set; }
public Uri CurrentSource { get; }
public bool CanGoForward { get; }
public bool SandboxExternalContent { get; set; }
public NavigationService NavigationService { get; }
public bool CanGoBack { get; }
public event NavigatingCancelEventHandler Navigating;
public event NavigationProgressEventHandler NavigationProgress;
public event NavigatedEventHandler Navigated;
public event LoadCompletedEventHandler LoadCompleted;
public event NavigationFailedEventHandler NavigationFailed;
public event FragmentNavigationEventHandler FragmentNavigation;
public event NavigationStoppedEventHandler NavigationStopped;
public void AddBackEntry(CustomContentState state);
public void GoBack();
public void GoForward();
public bool Navigate(Uri source);
public bool Navigate(Uri source, object extraData);
public bool Navigate(object content);
public bool Navigate(object content, object extraData);
public override void OnApplyTemplate();
public void Refresh();
public JournalEntry RemoveBackEntry();
public override bool ShouldSerializeContent();
public void StopLoading();
protected override void AddChild(object value);
protected override void AddText(string text);
protected override void OnClosed(EventArgs args);
protected override AutomationPeer OnCreateAutomationPeer();
}
接下来,我们来分析它的属性成员和方法成员,看看这个导航窗体到底为开发者提供了哪些便利。
属性成员
属性名 | 说明 |
BackStack | 获取导航窗体可以回退的导航历史条目 |
ForwardStack | 获取导航窗体可以前进的导航历史条目 |
ShowsNavigationUI | 是否显示导航UI |
Source | 获取或设置导航内容,它是一个统一资源标识符 |
CurrentSource | 获取上次导航内容的统一资源标识符 |
CanGoForward | 获取一个值,该值指示在前进导航历史记录中是否具有至少一个条目。 |
SandboxExternalContent | |
NavigationService | 获取导航服务 |
CanGoBack | 获取一个值,该值指示导航历史记录中是否有至少一个条目。 |
在上面表中,Source属性最为重要,它表示设置要导航的内容,而这些内容可以是任何.NET Framework对象或 HTML 文件。
比如我们可以给Source设置一个网址,Source="https://www.baidu.com"。启动后,NavigationWindow的内容便会加载这个网页。
也可以通过C#代码的方式导航到某个网页。下面的示例用到了NavigationWindow 的Navigate方法成员,这个方法表示异步导航到由指定的内容 统一资源标识符 (URI)。
public partial class PageWindow : NavigationWindow
{
public PageWindow()
{
InitializeComponent();
this.Navigate(new Uri("https://www.baidu.com"));
}
}
关于NavigationWindow 的导航操作,还有两个常用的方法成员,分别是GoBack和GoForward。
GoBack()表示导航到上一页。
GoForward()表示导航到下一页。
二、创建NavigationWindow 窗体
Visual Studio 没有提供创建NavigationWindow窗体的菜单,但是我们可以先创建一个Window窗体,然后将这个窗体的改成继承NavigationWindow。记得前后端都要修改,例如我们来创建一个名叫PageWindow的NavigationWindow窗体。如下所示:
<NavigationWindow x:Class="HelloWorld.PageWindow"
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:HelloWorld"
mc:Ignorable="d"
Title="WPF中文网 - 页面导航课程" Height="450" Width="800">
</NavigationWindow>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace HelloWorld
{
/// <summary>
/// PageWindow.xaml 的交互逻辑
/// </summary>
public partial class PageWindow : NavigationWindow
{
public PageWindow()
{
InitializeComponent();
this.Navigate(new Uri("https://www.baidu.com"));
}
}
}
如果要将这个窗体做为第一启动窗体,我们需要修改App.xaml中的StartupUri属性。
<Application x:Class="HelloWorld.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:HelloWorld"
StartupUri="PageWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>
三、开始页面导航
在本例中,我们准备了3个Page页,分别是Page1、Page2和Page3。下面是3个页面的源代码。
Page1页面
<Page x:Class="HelloWorld.Page1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:HelloWorld"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="Page1">
<Grid>
<TextBlock Text="Page1 - 点我进入Page2"
MouseUp="TextBlock_MouseUp"
FontSize="60"
Foreground="DarkCyan"/>
<TextBlock x:Name="_timeTextBlock" Margin="0,100,0,0"/>
</Grid>
</Page>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace HelloWorld
{
/// <summary>
/// Page1.xaml 的交互逻辑
/// </summary>
public partial class Page1 : Page
{
public Page1()
{
InitializeComponent();
_timeTextBlock.Text = DateTime.Now.ToString();
}
private void TextBlock_MouseUp(object sender, MouseButtonEventArgs e)
{
//有3种方式可以导航到Page2,但是我们选择了第二种
//注意Page2被实例化后,在每次前进或后退的操作中,Page2的时间是不会变化的
//这是因为导航日志记录了当前页面。
//第Page1和Page3每次进入时,时间都会发生变化
//第1种导航方式
//NavigationService ns = NavigationService.GetNavigationService(this);
//ns.Navigate(new Uri("Page2.xaml", UriKind.Relative));
//第2种导航方法
Page2 page2 = new Page2();
this.NavigationService.Navigate(page2);
//第3种导航方式
//this.NavigationService.Navigate(new Uri("Page2.xaml", UriKind.Relative));
}
}
}
Page2页面
<Page x:Class="HelloWorld.Page2"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:HelloWorld"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="Page2">
<Grid>
<TextBlock Text="Page2 点我导航到Page3"
FontSize="60"
MouseUp="TextBlock_MouseUp"
Foreground="DarkOrange"/>
<TextBlock x:Name="_timeTextBlock" Margin="0,100,0,0"/>
</Grid>
</Page>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace HelloWorld
{
/// <summary>
/// Page2.xaml 的交互逻辑
/// </summary>
public partial class Page2 : Page
{
public Page2()
{
InitializeComponent();
_timeTextBlock.Text = DateTime.Now.ToString();
}
private void TextBlock_MouseUp(object sender, MouseButtonEventArgs e)
{
this.NavigationService.Navigate(new Uri("Page3.xaml", UriKind.Relative));
}
}
}
Page3页面
<Page x:Class="HelloWorld.Page3"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:HelloWorld"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="800"
Title="Page3">
<Grid>
<TextBlock Text="Page3 我是最后一页"
FontSize="60"
Foreground="DarkOliveGreen"/>
<TextBlock x:Name="_timeTextBlock" Margin="0,100,0,0"/>
</Grid>
</Page>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace HelloWorld
{
/// <summary>
/// Page3.xaml 的交互逻辑
/// </summary>
public partial class Page3 : Page
{
public Page3()
{
InitializeComponent();
_timeTextBlock.Text = DateTime.Now.ToString();
}
}
}
默认加载第一页
<NavigationWindow x:Class="HelloWorld.PageWindow"
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:HelloWorld"
mc:Ignorable="d"
Title="WPF中文网 - 页面导航课程" Height="450" Width="800">
<NavigationWindow.Source>
Page1.xaml
</NavigationWindow.Source>
</NavigationWindow>
在NavigationWindow 导航窗体中,默认我们通过设置Source属性,加载 Page1.xaml。最后调试运行,程序将从Page1导航到Page2,又可以从Page2导航到Page3,但是,Page3不可再导航了,因为没有实现业务。如果要从Page3回到Page2或Page1,只能依赖于NavigationWindow 提供的GoBack和GoForward成员。
这里需要着重说明的是,我们有三种方式可以实现页面的导航。
//第1种导航方式
NavigationService ns = NavigationService.GetNavigationService(this);
ns.Navigate(new Uri("Page2.xaml", UriKind.Relative));
//第2种导航方法
Page2 page2 = new Page2();
this.NavigationService.Navigate(page2);
//第3种导航方式
this.NavigationService.Navigate(new Uri("Page2.xaml", UriKind.Relative));
这三种方式中,只有第二种是原地实例化了一个页面,这个对象最终会进入导航日志容器中,我们在本例中给3个页面都显示了当前系统时间,在执行NavigationWindow 提供的GoBack和GoForward成员时,只有Page2的时间停留在最初导航的时候,说明导航日志是可以暂存页面实例的。
最后,来看一下导航运行效果。
当前课程源码下载:(注明:本站所有源代码请按标题搜索)
文件名:111-《NavigationWindow导航窗体》-源代码
链接:https://pan.baidu.com/s/1yu-q4tUtl0poLVgmcMfgBA
提取码:wpff
——重庆教主 2023年11月24日