WPF中文网

NavigationWindow导航窗体

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日

copyright @重庆教主 WPF中文网 联系站长:(QQ)23611316 (微信)movieclip (QQ群).NET小白课堂:864486030 | 本文由WPF中文网原创发布,谢绝转载 渝ICP备2023009518号-1