导航概述

Windows Presentation Foundation (WPF) 支持可在两种类型的应用程序中使用的浏览器样式导航:独立应用程序和 XAML 浏览器应用程序(XBAP)。 若要打包导航内容,WPF 提供类 Page 。 可以通过使用Hyperlink以声明方式导航,或通过使用NavigationService以编程方式从一个Page导航到另一个。 WPF 使用导航记录来记住以前导航过的页面,并进行回退导航。

PageHyperlinkNavigationService和日记构成了 WPF 提供的导航支持的核心。 本概述详细介绍了这些功能,然后介绍高级导航支持,其中包括导航到松散的可扩展应用程序标记语言(XAML)文件、HTML 文件和对象。

注释

在本主题中,术语“browser”仅指可以托管 WPF 应用程序的浏览器,这些浏览器当前包括 internet Explorer 和 Firefox Microsoft。 如果特定 WPF 功能仅受特定浏览器支持,则引用浏览器版本。

本主题概述了 WPF 中的关键导航功能。 这些功能适用于独立应用程序和 XBAP,尽管本主题在 XBAP 的上下文中提供了这些功能。

注释

本主题不讨论如何生成和部署 XBAP。 有关 XBAP 的详细信息,请参阅 WPF XAML 浏览器应用程序概述

本部分介绍并演示导航的以下方面:

实现页面

在 WPF 中,可以导航到多个内容类型,其中包括 .NET Framework 对象、自定义对象、枚举值、用户控件、XAML 文件和 HTML 文件。 但是,你会发现打包内容的最常用和便捷方法是使用 Page。 此外, Page 实现特定于导航的功能,以增强其外观并简化开发。

使用 Page时,可以使用如下所示的标记以声明方式实现 XAML 内容的可导航页。

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />

在 XAML 标记中实现的 PagePage 为根元素,并且需要声明 WPF XML 命名空间。 该 Page 元素包含要导航到和显示的内容。 通过设置 Page.Content 属性元素来添加内容,如以下标记所示。

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <Page.Content>
    <!-- Page Content -->
    Hello, Page!
  </Page.Content>
</Page>

Page.Content 只能包含一个子元素;在前面的示例中,内容是单个字符串“Hello, Page!”在实践中,通常使用布局控件作为子元素(请参阅 布局)来包含和撰写内容。

元素的 Page 子元素被视为元素 Page 的内容,因此,无需使用显式 Page.Content 声明。 以下标记是与前面的示例等效的声明性标记。

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <!-- Page Content -->
  Hello, Page!
</Page>

在这种情况下, Page.Content 会自动使用元素的 Page 子元素进行设置。 有关详细信息,请参阅 WPF 内容模型

仅限标记的 Page 对于显示内容很有用。 但是,还可以 Page 显示允许用户与页面交互的控件,并且可以通过处理事件和调用应用程序逻辑来响应用户交互。 交互式 Page 通过结合标记和后台代码实现,如以下示例所示。

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.HomePage">
  Hello, from the XBAP HomePage!
</Page>
using System.Windows.Controls;

namespace SDKSample
{
    public partial class HomePage : Page
    {
        public HomePage()
        {
            InitializeComponent();
        }
    }
}

Imports System.Windows.Controls

Namespace SDKSample
    Partial Public Class HomePage
        Inherits Page
        Public Sub New()
            InitializeComponent()
        End Sub
    End Class
End Namespace

若要允许标记文件和代码隐藏文件协同工作,需要以下配置:

  • 在标记中,Page元素必须包含x:Class属性。 生成应用程序时,标记文件中的存在 x:Class 会导致Microsoft生成引擎(MSBuild)创建 partial 派生自 Page 并具有属性指定的名称的 x:Class 类。 这需要为 XAML 架构添加 XML 命名空间声明( xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" )。 生成的 partial 类实现,该实现 InitializeComponent调用以注册事件并设置在标记中实现的属性。

  • 在代码隐藏中,类必须是一个与标记中由 x:Class 属性指定的同名的 partial 类,并且还必须派生自 Page。 这样,后台代码文件就可以与应用程序生成时为标记文件生成的 partial 类相关联(请参阅 生成 WPF 应用程序)。

  • 在代码隐藏中,Page 类必须实现一个构造函数,该构造函数调用 InitializeComponent 方法。 InitializeComponent 由标记文件的生成的 partial 类实现,用于注册事件并设置标记中定义的属性。

注释

使用 Visual Studio 向项目中添加新的 Page 时,Page 将通过标记和后台代码实现,并包括用于创建标记与后台代码文件之间关联的必要配置,详见此处。

一旦你有了 Page,你就可以导航到它。 若要指定应用程序导航到的第一个 Page ,需要配置启动 Page

配置起始页

XBAP 要求在浏览器中托管一定数量的应用程序基础结构。 在 WPF 中,该 Application 类是建立所需应用程序基础结构的应用程序定义的一部分(请参阅 应用程序管理概述)。

应用程序定义通常通过标记和后台代码来实现,其中标记文件被配置为 MSBuildApplicationDefinition 项。 下面是 XBAP 的应用程序定义。

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.App" />
using System.Windows;

namespace SDKSample
{
    public partial class App : Application { }
}

Imports System.Windows

Namespace SDKSample
    Partial Public Class App
        Inherits Application
    End Class
End Namespace

XBAP 可以使用其应用程序定义来指定一个启动点 Page,即在启动 XBAP 时自动加载的 Page。 为了做到这一点,可以通过将目标Page的统一资源标识符(URI)设置为StartupUri属性。

注释

在大多数情况下,Page 要么编译到应用程序中,或者与应用程序一起部署。 在这些情况下,标识一个 Page 的 URI 是一个包 URI,它是符合 方案的 URI。 在WPF 中的包 URI中进一步讨论了包 URI。 还可以使用下面讨论的 http 方案导航到内容。

可以在标记中以声明方式设置 StartupUri ,如以下示例所示。

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.App"
    StartupUri="PageWithHyperlink.xaml" />

在此示例中,该 StartupUri 属性使用标识 HomePage.xaml 的相对包 URI 进行设置。 启动 XBAP 时,HomePage.xaml 会自动导航到并显示。 下图演示了这一点,该图显示了从 Web 服务器启动的 XBAP。

XBAP 页

注释

有关 XBAP 开发和部署的详细信息,请参阅 WPF XAML 浏览器应用程序概述部署 WPF 应用程序

配置主机窗口的标题、宽度和高度

你可能从上图中注意到的一件事是,浏览器和选项卡面板的标题都是 XBAP 的 URI。 除了很长,标题既没有吸引力,也信息量不大。 因此, Page 可以通过设置 WindowTitle 属性来更改标题。 此外,还可以分别通过设置 WindowWidthWindowHeight 来配置浏览器窗口的宽度和高度。

WindowTitleWindowWidth以及WindowHeight可以在标记中以声明方式设置,如以下示例所示。

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.HomePage"
    WindowTitle="Page Title"
    WindowWidth="500"
    WindowHeight="200">
  Hello, from the XBAP HomePage!
</Page>

下图显示了结果。

窗口标题、高度、宽度

典型的 XBAP 包含多个页面。 从一个页面导航到另一个页面的最简单方法是使用 a Hyperlink. 可以使用Hyperlink元素以声明的方式将Hyperlink添加到Page,如下标记所示。

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page With Hyperlink"
  WindowWidth="250"
  WindowHeight="250">
<Hyperlink NavigateUri="UriOfPageToNavigateTo.xaml">
  Navigate to Another Page
</Hyperlink>
</Page>

元素 Hyperlink 需要以下各项:

  • 要导航到的 Page 包 URI,由 NavigateUri 属性指定。

  • 用户可以单击的内容来启动导航,例如文本和图像(对于元素可以包含的内容 Hyperlink ,请参阅 Hyperlink)。

下图显示了具有Hyperlink的 XBAP,其中包含Page

带有超链接的页面

正如预期的那样,单击 Hyperlink 会导致 XBAP 导航到由 NavigateUri 属性标识的 Page。 此外,XBAP 还向 Internet Explorer 中的“最近页面”列表中添加了一个关于前 Page 的条目。 如下图所示。

后退和向前按钮

除了支持从一个 Page 导航到另一个 Hyperlink 导航,Hyperlink 还支持片段导航。

段落导航

片段导航 是指向当前 Page 或其他 Page内容片段的导航。 在 WPF 中,内容片段是由命名元素包含的内容。 命名元素是具有其 Name 属性集的元素。 以下标记显示了包含内容片段的命名 TextBlock 元素。

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    WindowTitle="Page With Fragments" >
<!-- Content Fragment called "Fragment1" -->
<TextBlock Name="Fragment1">
  Ea vel dignissim te aliquam facilisis ...
</TextBlock>
</Page>

Hyperlink若要导航到内容片段,该NavigateUri属性必须包括以下内容:

  • 用于导航到内容片段的 Page 的 URI。

  • 一个“#”字符。

  • 包含内容片段的 Page 元素的名称。

片段 URI 具有以下格式。

PageURI#ElementName

下面显示了一个配置为导航到内容片段的 Hyperlink 示例。

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page That Navigates To Fragment" >
<Hyperlink NavigateUri="PageWithFragments.xaml#Fragment1">
  Navigate To pack Fragment
</Hyperlink>
</Page>

注释

本部分介绍 WPF 中的默认片段导航实现。 WPF 还允许你实现自己的片段导航方案,这部分需要处理事件 NavigationService.FragmentNavigation

重要

仅当页面可以通过 HTTP 浏览时,才能导航到松散 XAML 页面的片段(即以Page作为根元素的仅标记 XAML 文件)。

但是,独立的 XAML 页面可以导航到它自己的片段。

虽然 Hyperlink 允许用户启动到特定 Page位置的导航,但查找和下载页面的工作由 NavigationService 类执行。 实质上, NavigationService 提供代表客户端代码处理导航请求的功能,例如 Hyperlink。 此外, NavigationService 实现对跟踪和影响导航请求的更高级别支持。

单击Hyperlink时,WPF 调用NavigationService.Navigate以定位并下载指定的Page处的包 URI。 下载的Page被转换为一个对象树,其中其根对象是下载的Page的一个实例。 对根 Page 对象的引用存储在属性中 NavigationService.Content 。 导航到的内容的包 URI 存储在属性中 NavigationService.Source ,而 NavigationService.CurrentSource 存储导航到的最后一页的包 URI。

注释

WPF 应用程序可能有多个当前激活的 NavigationService。 有关详细信息,请参阅本主题后面的 导航主机

使用导航服务的编程导航

如果导航是通过在标记中使用Hyperlink以声明方式实现的,那么您无需了解NavigationService,因为Hyperlink已经为您使用NavigationService了。 这意味着,只要导航主机的 Hyperlink 直接或间接父级是导航主机(请参阅 导航主机), Hyperlink 就可以查找和使用导航主机的导航服务来处理导航请求。

但是,在某些情况下,需要直接使用 NavigationService ,包括以下内容:

  • 需要实例化 Page 使用非无参数构造函数时。

  • 在导航到 Page 之前,需要设置其属性。

  • 当需要导航到的Page只能在运行时确定。

在这些情况下,需要编写代码以编程方式通过调用 Navigate 对象的方法 NavigationService 来启动导航。 这需要获取NavigationService的引用。

获取对 NavigationService 的引用

由于 导航主机 部分涵盖的原因,WPF 应用程序可以有多个 NavigationService。 这意味着你的代码需要一种方法来查找 NavigationService,这通常是通过 NavigationService 导航到当前的 Page。 可以通过调用staticNavigationService.GetNavigationService该方法来获取对 a NavigationService 的引用。 若要获取导航到特定 PageNavigationService,请将对 Page 的引用作为 GetNavigationService 方法的参数传递。 以下代码演示如何获取当前PageNavigationService

using System.Windows.Navigation;
// Get a reference to the NavigationService that navigated to this Page
NavigationService ns = NavigationService.GetNavigationService(this);
' Get a reference to the NavigationService that navigated to this Page
Dim ns As NavigationService = NavigationService.GetNavigationService(Me)

作为查找 NavigationService 对象的 Page快捷方式, Page 实现该 NavigationService 属性。 下面的示例演示了此操作。

using System.Windows.Navigation;
// Get a reference to the NavigationService that navigated to this Page
NavigationService ns = this.NavigationService;
' Get a reference to the NavigationService that navigated to this Page
Dim ns As NavigationService = Me.NavigationService

注释

Page触发Loaded事件时,A Page才能获取对其NavigationService的引用。

以编程方式导航到页面对象

以下示例演示如何使用 NavigationService 以编程方式导航到 a Page. 必须使用编程导航,因为目标 Page 只能通过一个带参数的构造函数实例化。 以下是带有非零参数构造函数的Page标记和代码。

<Page
    x:Class="SDKSample.PageWithNonDefaultConstructor"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="PageWithNonDefaultConstructor">
  
  <!-- Content goes here -->
  
</Page>
using System.Windows.Controls;

namespace SDKSample
{
    public partial class PageWithNonDefaultConstructor : Page
    {
        public PageWithNonDefaultConstructor(string message)
        {
            InitializeComponent();

            this.Content = message;
        }
    }
}

Namespace SDKSample
    Partial Public Class PageWithNonDefaultConstructor
        Inherits Page
        Public Sub New(ByVal message As String)
            InitializeComponent()

            Me.Content = message
        End Sub
    End Class
End Namespace

导航到PagePage函数将在以下标记和代码中展示,该函数使用非无参数构造函数。

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.NSNavigationPage">

  <Hyperlink Click="hyperlink_Click">
    Navigate to Page with Non-Default Constructor
  </Hyperlink>

</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class NSNavigationPage : Page
    {
        public NSNavigationPage()
        {
            InitializeComponent();
        }

        void hyperlink_Click(object sender, RoutedEventArgs e)
        {
            // Instantiate the page to navigate to
            PageWithNonDefaultConstructor page = new PageWithNonDefaultConstructor("Hello!");

            // Navigate to the page, using the NavigationService
            this.NavigationService.Navigate(page);
        }
    }
}

Namespace SDKSample
    Partial Public Class NSNavigationPage
        Inherits Page
        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub hyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Instantiate the page to navigate to
            Dim page As New PageWithNonDefaultConstructor("Hello!")

            ' Navigate to the page, using the NavigationService
            Me.NavigationService.Navigate(page)
        End Sub
    End Class
End Namespace

单击Hyperlink上的Page后,将通过使用非无参数构造函数实例化Page并调用NavigationService.Navigate方法来启动导航。 Navigate 接受对要导航到的对象 NavigationService (而不是包 URI)的引用。

使用 Pack URI 进行程序化导航

如果需要以编程方式构造包 URI(例如,在运行时只能确定包 URI 时),可以使用该方法 NavigationService.Navigate 。 下面的示例演示了此操作。

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.NSUriNavigationPage">
  <Hyperlink Click="hyperlink_Click">Navigate to Page by Pack URI</Hyperlink>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class NSUriNavigationPage : Page
    {
        public NSUriNavigationPage()
        {
            InitializeComponent();
        }

        void hyperlink_Click(object sender, RoutedEventArgs e)
        {
            // Create a pack URI
            Uri uri = new Uri("AnotherPage.xaml", UriKind.Relative);

            // Get the navigation service that was used to
            // navigate to this page, and navigate to
            // AnotherPage.xaml
            this.NavigationService.Navigate(uri);
        }
    }
}

Namespace SDKSample
    Partial Public Class NSUriNavigationPage
        Inherits Page
        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub hyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Create a pack URI
            Dim uri As New Uri("AnotherPage.xaml", UriKind.Relative)

            ' Get the navigation service that was used to 
            ' navigate to this page, and navigate to 
            ' AnotherPage.xaml
            Me.NavigationService.Navigate(uri)
        End Sub
    End Class
End Namespace

刷新当前页

如果 APage具有与存储在NavigationService.Source属性中的包 URI 相同的包 URI,则不会被下载。 若要强制 WPF 再次下载当前页,可以调用 NavigationService.Refresh 该方法,如以下示例所示。

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.NSRefreshNavigationPage">
 <Hyperlink Click="hyperlink_Click">Refresh this page</Hyperlink>
</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class NSRefreshNavigationPage : Page
    {

Namespace SDKSample
    Partial Public Class NSRefreshNavigationPage
        Inherits Page
        void hyperlink_Click(object sender, RoutedEventArgs e)
        {
            // Force WPF to download this page again
            this.NavigationService.Refresh();
        }
    }
}
        Private Sub hyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Force WPF to download this page again
            Me.NavigationService.Refresh()
        End Sub
    End Class
End Namespace

有许多方法可以启动导航,如你所见。 当导航启动时,以及导航过程中,您可以使用由NavigationService实现的以下事件来跟踪和调整导航:

  • Navigating。 请求新导航时发生。 可用于取消导航。

  • NavigationProgress。 在下载过程中定期发生,以提供导航进度信息。

  • Navigated。 当页面已找到并下载时发生。

  • NavigationStopped。 当导航被停止(通过调用 StopLoading)时发生此事件,或者在当前导航进行中请求新的导航时发生此事件。

  • NavigationFailed。 在导航到请求的内容时引发错误时发生。

  • LoadCompleted。 在加载和分析导航到的内容并已开始呈现时发生。

  • FragmentNavigation。 导航到内容片段时发生,这种情况发生在以下情况:

    • 如果所需的片段位于当前内容中,则立即。

    • 加载源内容后,如果所需的片段位于不同的内容中。

导航事件是按照下图所示的顺序触发的。

页面导航流程图

一般情况下, Page 不关心这些事件。 应用程序可能更关注这些事件,因此,Application 类也会引发它们。

每次 NavigationService 引发事件时,类 Application 都会引发相应的事件。 FrameNavigationWindow 提供相同的事件,用于检测各自范围内的导航。

在某些情况下,Page 可能会对这些事件感兴趣。 例如,Page 可以处理 NavigationService.Navigating 事件,以确定是否取消离开自己的导航。 下面的示例演示了此操作。

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.CancelNavigationPage">
  <Button Click="button_Click">Navigate to Another Page</Button>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class CancelNavigationPage : Page
    {
        public CancelNavigationPage()
        {
            InitializeComponent();

            // Can only access the NavigationService when the page has been loaded
            this.Loaded += new RoutedEventHandler(CancelNavigationPage_Loaded);
            this.Unloaded += new RoutedEventHandler(CancelNavigationPage_Unloaded);
        }

        void button_Click(object sender, RoutedEventArgs e)
        {
            // Force WPF to download this page again
            this.NavigationService.Navigate(new Uri("AnotherPage.xaml", UriKind.Relative));
        }

        void CancelNavigationPage_Loaded(object sender, RoutedEventArgs e)
        {
            this.NavigationService.Navigating += new NavigatingCancelEventHandler(NavigationService_Navigating);
        }

        void CancelNavigationPage_Unloaded(object sender, RoutedEventArgs e)
        {
            this.NavigationService.Navigating -= new NavigatingCancelEventHandler(NavigationService_Navigating);
        }

        void NavigationService_Navigating(object sender, NavigatingCancelEventArgs e)
        {
            // Does the user really want to navigate to another page?
            MessageBoxResult result;
            result = MessageBox.Show("Do you want to leave this page?", "Navigation Request", MessageBoxButton.YesNo);

            // If the user doesn't want to navigate away, cancel the navigation
            if (result == MessageBoxResult.No) e.Cancel = true;
        }
    }
}

Namespace SDKSample
    Partial Public Class CancelNavigationPage
        Inherits Page
        Public Sub New()
            InitializeComponent()

            ' Can only access the NavigationService when the page has been loaded
            AddHandler Loaded, AddressOf CancelNavigationPage_Loaded
            AddHandler Unloaded, AddressOf CancelNavigationPage_Unloaded
        End Sub

        Private Sub button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Force WPF to download this page again
            Me.NavigationService.Navigate(New Uri("AnotherPage.xaml", UriKind.Relative))
        End Sub

        Private Sub CancelNavigationPage_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
            AddHandler NavigationService.Navigating, AddressOf NavigationService_Navigating
        End Sub

        Private Sub CancelNavigationPage_Unloaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
            RemoveHandler NavigationService.Navigating, AddressOf NavigationService_Navigating
        End Sub

        Private Sub NavigationService_Navigating(ByVal sender As Object, ByVal e As NavigatingCancelEventArgs)
            ' Does the user really want to navigate to another page?
            Dim result As MessageBoxResult
            result = MessageBox.Show("Do you want to leave this page?", "Navigation Request", MessageBoxButton.YesNo)

            ' If the user doesn't want to navigate away, cancel the navigation
            If result = MessageBoxResult.No Then
                e.Cancel = True
            End If
        End Sub
    End Class
End Namespace

如果将处理程序注册到来自 Page 的导航事件,就像前面示例所示,则还必须取消注册事件处理程序。 如果不这样做,可能会影响WPF导航使用日记记住Page导航时出现副作用。

使用日记记住导航

WPF 使用两个堆栈来记住已从中导航的页面:后退堆栈和向前堆栈。 从当前 Page 导航到新的 Page 或转发到现有的 Page时,当前 Page 将添加到 后堆栈。 当您从当前 Page 返回到上一个 Page 时,当前的 Page 将被添加到 前进栈中。 后堆栈、前向堆栈以及管理它们的功能统称为日记。 后堆栈和前向堆栈中的每个项都是类的 JournalEntry 实例,称为 日记条目

从概念上讲,日记的工作方式与 Internet Explorer 中的 “后 退”和 “转发 ”按钮的工作方式相同。 下图显示了这些内容。

后退和向前按钮

对于 Internet Explorer 托管的 XBAP,WPF 会将日记集成到 Internet Explorer 的导航 UI 中。 这样,用户就可以使用 Internet Explorer 中的 “后退”、“ 转发”和“ 最近页面 ”按钮在 XBAP 中导航页面。

重要

在 Internet Explorer 中,当用户离开和返回 XBAP 时,只会在日记中保留未保持活动状态的页面的日记条目。 有关使页面保持活动状态的讨论,请参阅本主题后面的 “页面生存期”和“日记 ”。

默认情况下,出现在Internet Explorer中“最近页面”列表的每个Page的文本都是该Page的URI。 在许多情况下,这对用户来说并不特别有意义。 幸运的是,可以使用以下选项更改文本:

  1. 附加的JournalEntry.Name属性值

  2. Page.Title属性值。

  3. 当前Page.WindowTitle的属性值和Page的 URI。

  4. Page的当前 URI。 (默认值)

列出选项的顺序与查找文本的优先级顺序匹配。 例如,如果 JournalEntry.Name 已设置,则忽略其他值。

以下示例使用 Page.Title 特性更改为日记条目显示的文本。

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.PageWithTitle"
    Title="This is the title of the journal entry for this page.">
</Page>
using System.Windows.Controls;

namespace SDKSample
{
    public partial class PageWithTitle : Page
    {

Namespace SDKSample
    Partial Public Class PageWithTitle
        Inherits Page
    }
}
    End Class
End Namespace

尽管用户可以使用 Internet Explorer 中的 “后退”、“ 转发”和“ 最近使用页面 ”来导航日记,但也可以使用 WPF 提供的声明性和编程机制导航日记。 这样做的一个原因是在页面中提供自定义导航 UI。

可以通过使用NavigationCommands公开的导航命令,以声明方式添加日志导航支持。 以下示例演示如何使用 BrowseBack 导航命令。

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.NavigationCommandsPage">
<Hyperlink Command="NavigationCommands.BrowseBack">Back</Hyperlink>
<Hyperlink Command="NavigationCommands.BrowseForward">Forward</Hyperlink>
</Page>

可以通过使用类的下列 NavigationService 成员之一,以编程方式导航日志。

日志还可以通过编程方式操作,正如本主题后面部分的“保留内容状态与导航历史记录” 中所述。

页面生存期和日志

假设 XBAP 包含多个包含丰富内容的页面,包括图形、动画和媒体。 此类页面的内存占用空间可能相当大,尤其是在使用视频和音频媒体时。 鉴于日志“记住”已导航到的页面,此类 XBAP 可以快速消耗大量且显著的内存。

因此,日志的默认行为是将元数据存储在 Page 每个日记条目中,而不是对 Page 对象的引用。 导航到日记条目时,其 Page 元数据用于创建指定 Page实例的新实例。 因此,导航的每个 Page 都有下图所示的生存期。

页面生存期

尽管使用默认日记行为可以节省内存消耗,但每页呈现性能可能会降低,因此重新实例化一个 Page 可能是耗费时间的,特别是如果它有很多内容。 如果需要在日记中保留 Page 实例,可以借鉴两种方法来执行此作。 首先,可以通过调用NavigationService.Navigate方法以编程方式导航到Page对象。

其次,可以通过将属性设置为true(默认值为false)来指定 WPF 保留日记中的实例PageKeepAlive 如以下示例所示,可以在标记中以声明方式设置 KeepAlive

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.KeepAlivePage"
    KeepAlive="True">
  
  An instance of this page is stored in the journal.
  
</Page>

保持活动状态的 Page 生存期与不处于活动状态的生存期略有不同。 首次导航到保持活动状态的 Page 时,它会像不保持活动状态的 Page 一样被实例化。 但是,由于日志中的 Page 实例保留在日记中,只要它保留在日记中,它就不会再次实例化。 因此,如果 Page 有某个初始化逻辑需要在每次导航到 Page 时调用,则应将其从构造函数中移到 Loaded 事件的处理程序中。 如下图所示,每次导航到Page时仍会引发Loaded事件,从Page导航时会引发Unloaded事件。

当加载事件和卸载事件被引发时

Page 未保持活动状态时,不应执行以下任一操作:

  • 存储对它的引用或其任何部分。

  • 将事件处理程序绑定到未由其实现的事件上。

执行任一操作将创建引用,迫使Page保留在内存中,即使它已从日志中删除。

通常,应首选默认 Page 行为,即不保持 Page 活动状态。 但是,这具有下一部分讨论的状态影响。

使用导航历史记录保留内容状态

Page如果未保持连线,并且它含有用于从用户处收集数据的控件,那么如果用户离开然后回到Page,数据会发生什么情况? 从用户体验的角度来看,用户应该会看到之前输入的数据。 遗憾的是,由于每个导航都创建了一个新实例 Page ,因此将重新初始化收集数据的控件,并丢失数据。

幸运的是,该日志支持数据在 Page 导航中记住,包括控制数据。 具体而言,每个 Page 日志条目充当关联 Page 状态的临时容器。 以下步骤概述了从Page进行导航时此支持是如何使用的:

  1. 当前 Page 条目将添加到日志中。

  2. 该页的状态随该页的 Page 日记条目一起存储,该条目将添加到后堆栈中。

  3. 新的Page已被导航到。

当使用日志导航回页面 Page 时,将执行以下步骤:

  1. Page 将实例化(后台堆栈上的顶级日记条目)。

  2. 使用日志条目中存储的与 Page 相关的状态刷新 Page

  3. 已导航回 Page

当以下控件用于Page时,WPF 会自动使用此支持:

Page如果使用这些控件,则在Page导航过程中会保存输入的数据,如下图中所示的“收藏夹颜色ListBox

带有记住状态的控件页面

Page有控件不在上述列表中,或者当状态存储在自定义对象中时,需要编写代码,以确保日志在Page导航过程中记住状态。

如果需要记住导航中的Page小段状态,可以使用使用FrameworkPropertyMetadata.Journal元数据标志配置的依赖项属性(请参阅DependencyProperty)。

如果你需要在导航中记住的状态包含多个数据片段,你可能会发现,将状态封装在一个类中并实现 IProvideCustomContentState 接口会减少代码量。

如果需要在单个 Page的各种状态之间导航,而无需从 Page 本身导航,则可以使用 IProvideCustomContentStateNavigationService.AddBackEntry

饼干

WPF 应用程序存储数据的另一种方法是使用 Cookie(使用 SetCookieGetCookie 方法创建、更新和删除)。 可以在 WPF 中创建的 Cookie 与其他类型的 Web 应用程序使用的 Cookie 相同;Cookie 是应用程序在应用程序会话期间或跨应用程序会话存储在客户端计算机上的任意数据片段。 Cookie 数据通常采用以下格式的名称/值对。

名字=价值

当数据与 Uri (指定设置 Cookie 的位置) 一起传递到 SetCookie时,会在内存中创建一个 Cookie,并且它仅在当前应用程序会话期间可用。 这种类型的 Cookie 称为 会话 Cookie

若要跨应用程序会话存储 Cookie,必须使用以下格式将过期日期添加到 Cookie。

名字=价值; expires=DAY, DD-MMM-YYYY HH:MM:SS GMT

过期日期的 Cookie 存储在当前 Windows 安装的临时 Internet 文件文件夹中,直到 Cookie 过期。 此类 Cookie 称为持久性 Cookie ,因为它在应用程序会话中持续存在。

通过调用 GetCookie 方法并传递使用 SetCookie 方法设置 Cookie 的位置 Uri,你可以检索会话和持久性 Cookie。

以下是 WPF 中支持 Cookie 的一些方法:

  • WPF 独立应用程序和 XBAP 可以创建和管理 Cookie。

  • 可以从浏览器访问 XBAP 创建的 Cookie。

  • 来自同一域的 XBAP 可以创建和共享 Cookie。

  • 同一域中的 XBAP 和 HTML 页面可以创建和共享 Cookie。

  • 当 XBAP 和松散 XAML 页面发出 Web 请求时,会发送 Cookie。

  • IFRAMES 中托管的 XBAP 和顶级 XBAP 都可以访问 Cookie。

  • WPF 中的 Cookie 支持对所有受支持的浏览器都是相同的。

  • 在 Internet Explorer 中,与 Cookie 相关的 P3P 策略受到 WPF 的尊重,尤其是在第一方和第三方 XBAP 方面。

结构化导航

如果需要将数据从一个Page传递到另一个Page,可以将数据作为参数传递给Page的非默认构造函数。 请注意,如果使用此技术,则必须保持 Page 有效,否则,下次导航到 Page 时,WPF 会使用无参数构造函数重新实例化 Page

或者,您的 Page 可以实现一些属性,这些属性是用需要传递的数据进行设置的。 当Page需要将数据传回导航到它的Page时,事情变得棘手。 问题在于,导航本身没有支持确保从 Page 导航后能够返回的机制。 从本质上讲,导航不支持调用/返回语义。 为了解决此问题,WPF 提供了PageFunction<T>类,该类可用于确保Page以可预测的结构化方式返回。 有关详细信息,请参阅 结构化导航概述

NavigationWindow 类

至此,你已了解了最可能用于生成具有可导航内容的应用程序的导航服务的范围。 这些服务在 XBAP 的上下文中进行了讨论,尽管它们不限于 XBAP。 新式作系统和 Windows 应用程序利用新式用户的浏览器体验,将浏览器样式的导航合并到独立应用程序中。 常见示例包括:

  • Word 同义词库:导航单词选项。

  • 文件资源管理器:导航文件和文件夹。

  • 向导:将复杂任务分解为可在两者之间导航的多个页面。 例如,用于处理添加和删除 Windows 功能的 Windows 组件向导。

若要将浏览器样式的导航合并到独立应用程序中,可以使用该 NavigationWindow 类。 NavigationWindow 派生自 Window,并扩展了与 XBAPs 提供的相同导航支持。 可以 NavigationWindow 用作独立应用程序的主窗口或辅助窗口,例如对话框。

若要像在 WPF 中实现大多数顶级类(例如WindowPage)一样实现NavigationWindow,请结合使用标记和后台代码。 下面的示例演示了此操作。

<NavigationWindow
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.MainWindow" 
    Source="HomePage.xaml"/>
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class MainWindow : NavigationWindow
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

Namespace SDKSample
    Partial Public Class MainWindow
        Inherits NavigationWindow
        Public Sub New()
            InitializeComponent()
        End Sub
    End Class
End Namespace

此代码创建了一个 NavigationWindow 在打开 NavigationWindow 时自动导航至 Page (HomePage.xaml)。 NavigationWindow如果这是主应用程序窗口,则可以使用该StartupUri属性来启动它。 这显示在以下标记中。

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    StartupUri="MainWindow.xaml" />

下图显示了 NavigationWindow 作为独立应用程序的主窗口。

主窗口

从图中你可以看到,即使在前面的示例中实现代码没有设置,NavigationWindow 仍然有一个标题。 而是使用 WindowTitle 以下代码中显示的属性设置标题。

<Page 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    Title="Home Page"
    WindowTitle="NavigationWindow">
</Page>

设置WindowWidthWindowHeight属性也会影响NavigationWindow

通常,当你需要自定义 NavigationWindow 的行为或外观时,你可以实现自己的 NavigationWindow。 如果两者都没有,则可以使用快捷方式。 如果在独立应用程序中将 Page 指定为 StartupUriApplication 则会自动创建一个 NavigationWindow 来托管 Page。 以下标记演示如何启用此功能。

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    StartupUri="HomePage.xaml" />

如果希望辅助应用程序窗口(如对话框)成为一个 NavigationWindow,可以使用以下示例中的代码将其打开。

// Open a navigation window as a dialog box
NavigationWindowDialogBox dlg = new NavigationWindowDialogBox();
dlg.Source = new Uri("HomePage.xaml", UriKind.Relative);
dlg.Owner = this;
dlg.ShowDialog();
' Open a navigation window as a dialog box
Dim dlg As New NavigationWindowDialogBox()
dlg.Source = New Uri("HomePage.xaml", UriKind.Relative)
dlg.Owner = Me
dlg.ShowDialog()

下图显示了结果。

对话框

可以看到,显示 Internet Explorer 样式的 NavigationWindow“后退 ”和 “转发 ”按钮,允许用户导航日记。 这些按钮提供相同的用户体验,如下图所示。

导航窗口中的“后退”和“向前”

如果您的页面提供自己的浏览导航支持和 UI,可以通过将ShowsNavigationUI属性的值设置为false来隐藏NavigationWindow“后退”“前进”按钮。

或者,可以使用 WPF 中的自定义支持来替换其自身的 NavigationWindow UI。

Frame 类

浏览器和 NavigationWindow 窗口都是托管可导航内容的窗口。 在某些情况下,应用程序具有不需要由整个窗口托管的内容。 相反,此类内容嵌在其他内容中。 可以使用 Frame 类将可导航内容插入到其他内容中。 Frame 提供与 NavigationWindow XBAP 相同的支持。

以下示例演示如何使用Frame元素以声明方式将Frame添加到Page

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page that Hosts a Frame"
  WindowWidth="250"
  WindowHeight="250">
<Frame Source="FramePage1.xaml" />
</Page>

此标记将Source元素的属性设置为一个包 URI,用于PageFrame 应最初导航到此 URI。 以下图显示了一个包含 FramePage 的 XBAP,该 Frame 在多个页面之间导航。

在多个页面之间导航的框架

您不仅可以在 Page 的内容中使用 Frame。 在 Window 的内容中托管一个 Frame 也是很常见的。

默认情况下, Frame 仅在没有另一个日记的情况下使用自己的日记。 如果 Frame 是托管在 NavigationWindow 或 XBAP 中的内容的一部分,Frame 将使用属于 NavigationWindow 或 XBAP 的日记。 有时候,Frame 可能需要对它自己的日记负责。 这样做的一个原因是允许页面内的日记导航在由Frame托管的页面中进行。 下图对此进行了说明。

框架和页面关系图

在这种情况下,可以通过设置FrameJournalOwnership属性来配置Frame使用自己的日志。 这显示在以下标记中。

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page that Hosts a Frame"
  WindowWidth="250"
  WindowHeight="250">
<Frame Source="FramePage1.xaml" JournalOwnership="OwnsJournal" />
</Page>

下图说明了在使用自身日志的Frame中导航的效果。

使用自己日志的帧

请注意,日志条目由Frame中的导航 UI 显示,而不是由 Internet Explorer 显示。

注释

如果某个 Frame 是托管在某个 Window 内容中的一部分,Frame 则使用自己的日志,因此显示其自身的导航 UI。

如果你的用户体验需要Frame提供自己的日记而不显示导航 UI,那么可以通过将NavigationUIVisibility设置为Hidden来隐藏导航 UI。 这显示在以下标记中。

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page that Hosts a Frame"
  WindowWidth="250"
  WindowHeight="250">
<Frame 
  Source="FramePage1.xaml" 
  JournalOwnership="OwnsJournal" 
  NavigationUIVisibility="Hidden" />
</Page>

FrameNavigationWindow 称为导航主机的类。 导航主机是一个类,可以导航到和显示内容。 为此,每个导航主机都使用自己的 NavigationService 和日志。 导航主机的基本构造如下图所示。

导航器图:

从本质上讲,这允许 NavigationWindowFrame 在浏览器中托管时提供与 XBAP 相同的导航支持。

除了使用 NavigationService 和日记,导航主机还实现了与 NavigationService 相同的成员。 下图对此进行了说明。

在框架和导航窗口中的日志

这样,就可以直接针对它们进行导航支持的程序设计。 您可以考虑此选项,如果需要为托管在Window中的Frame提供自定义导航 UI。 此外,这两种类型实现了其他导航相关的成员,包括BackStackNavigationWindow.BackStackFrame.BackStack)和ForwardStackNavigationWindow.ForwardStackFrame.ForwardStack),这使得分别可以枚举后堆栈和前堆栈中的日记条目。

如前所述,应用程序中可以存在多个日记。 下图提供了一个示例,说明何时可以发生这种情况。

一个应用程序中有多个

在整个主题中,已使用 Page 和包 XBAP 来演示 WPF 的各种导航功能。 但是, Page 编译到应用程序中的不是唯一可以导航到的内容类型,而打包 XBAP 并不是标识内容的唯一方法。

如本部分所示,还可以导航到松散的 XAML 文件、HTML 文件和对象。

松散的 XAML 文件是具有以下特征的文件:

  • 仅包含 XAML(即无代码)。

  • 具有适当的命名空间声明。

  • 具有 .xaml 文件扩展名。

例如,请考虑作为松散 XAML 文件 Person.xaml 存储的以下内容。

<!-- Person.xaml -->
<TextBlock xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <TextBlock FontWeight="Bold">Name:</TextBlock>
  <TextBlock>Nancy Davolio</TextBlock>
  <LineBreak />
  <TextBlock FontWeight="Bold">Favorite Color:</TextBlock>
  <TextBlock>Yellow</TextBlock>
</TextBlock>

双击该文件时,浏览器将打开并导航到并显示内容。 如下图所示。

显示 Person.XAML 文件中的内容

可以通过以下方式显示松散的 XAML 文件:

  • 本地计算机、Intranet 或 Internet 上的网站。

  • 通用命名约定 (UNC) 文件共享。

  • 本地磁盘。

松散的 XAML 文件可以添加到浏览器的收藏夹,也可以是浏览器的主页。

注释

有关发布和启动松散 XAML 页面的详细信息,请参阅 部署 WPF 应用程序

与松散 XAML 相关的一个限制是,你只能托管可以在部分信任环境中安全运行的内容。 例如, Window 不能是松散 XAML 文件的根元素。 有关详细信息,请参阅 WPF 部分信任安全性

如你所预料的,你也可以导航到 HTML。 只需提供使用 http 方案的 URI 即可。 例如,以下 XAML 演示如何通过 Frame 导航到 HTML 页面。

<Frame Source="http://www.microsoft.com/default.aspx" />

导航到 HTML 需要特殊权限。 例如,无法通过在 Internet 区域部分信任安全沙盒中运行的 XBAP 进行导航。 有关详细信息,请参阅 WPF 部分信任安全性

WebBrowser 控件支持 HTML 文档托管、导航和脚本/托管代码互作性。 有关 WebBrowser 控件的详细信息,请参阅 WebBrowser

同样 Frame,导航到 HTML 使用 WebBrowser 需要特殊权限。 例如,从部分信任应用程序,只能导航到位于源站点的 HTML。 有关详细信息,请参阅 WPF 部分信任安全性

如果你有作为自定义对象存储的数据,则显示该数据的方法之一 Page 是创建绑定到这些对象的内容(请参阅 数据绑定概述)。 如果不需要创建整个页面的开销来显示对象,则可以直接导航到它们。

请考虑Person类在以下代码中的实现。

using System.Windows.Media;

namespace SDKSample
{
    public class Person
    {
        string name;
        Color favoriteColor;

        public Person() { }
        public Person(string name, Color favoriteColor)
        {
            this.name = name;
            this.favoriteColor = favoriteColor;
        }

        public string Name
        {
            get { return this.name; }
            set { this.name = value; }
        }

        public Color FavoriteColor
        {
            get { return this.favoriteColor; }
            set { this.favoriteColor = value; }
        }
    }
}

Namespace SDKSample
    Public Class Person
        Private _name As String
        Private _favoriteColor As Color

        Public Sub New()
        End Sub
        Public Sub New(ByVal name As String, ByVal favoriteColor As Color)
            Me._name = name
            Me._favoriteColor = favoriteColor
        End Sub

        Public Property Name() As String
            Get
                Return Me._name
            End Get
            Set(ByVal value As String)
                Me._name = value
            End Set
        End Property

        Public Property FavoriteColor() As Color
            Get
                Return Me._favoriteColor
            End Get
            Set(ByVal value As Color)
                Me._favoriteColor = value
            End Set
        End Property
    End Class
End Namespace

若要导航到它,请调用 NavigationWindow.Navigate 方法,如以下代码所示。

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
  x:Class="SDKSample.HomePage"
  WindowTitle="Page that Navigates to an Object">
<Hyperlink Name="hyperlink" Click="hyperlink_Click">
  Navigate to Nancy Davolio
</Hyperlink>
</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace SDKSample
{
    public partial class HomePage : Page
    {
        public HomePage()
        {
            InitializeComponent();
        }

        void hyperlink_Click(object sender, RoutedEventArgs e)
        {
            Person person = new Person("Nancy Davolio", Colors.Yellow);
            this.NavigationService.Navigate(person);
        }
    }
}

Namespace SDKSample
    Partial Public Class HomePage
        Inherits Page
        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub hyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Dim person As New Person("Nancy Davolio", Colors.Yellow)
            Me.NavigationService.Navigate(person)
        End Sub
    End Class
End Namespace

下图显示了结果。

导航到类的页面

在此图中,可以看到没有显示任何有用的内容。 事实上,显示的值是 Person 对象的方法的ToString返回值;默认情况下,这是 WPF 可用于表示对象的唯一值。 可以重写 ToString 该方法以返回更有意义的信息,尽管它仍将是字符串值。 可以利用 WPF 的呈现功能的一种方法是使用数据模板。 可以实现 WPF 可以与特定类型的对象关联的数据模板。 以下代码显示了对象的 Person 数据模板。

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="clr-namespace:SDKSample" 
    x:Class="SDKSample.App"
    StartupUri="HomePage.xaml">

  <Application.Resources>

    <!-- Data Template for the Person Class -->
    <DataTemplate DataType="{x:Type local:Person}">
      <TextBlock xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
        <TextBlock FontWeight="Bold">Name:</TextBlock>
        <TextBlock Text="{Binding Path=Name}" />
        <LineBreak />
        <TextBlock FontWeight="Bold">Favorite Color:</TextBlock>
        <TextBlock Text="{Binding Path=FavoriteColor}" />
      </TextBlock>
    </DataTemplate>
    
  </Application.Resources>

</Application>

在这里,数据模板通过使用x:Type属性中的DataType标记扩展与Person类型相关联。 然后,数据模板将 TextBlock 元素(见 TextBlock)绑定到类的属性 Person 。 下图显示了对象的更新外观 Person

导航到具有数据模板的类

此方法的优点是能够重复使用数据模板来一致地在应用程序中的任意位置显示对象,从而获得一致性。

有关数据模板的详细信息,请参阅 数据模板化概述

安全

WPF 导航支持允许通过 Internet 导航到 XBAP,并允许应用程序托管第三方内容。 为了保护应用程序和用户免受有害行为的影响,WPF 提供了在 安全和WPF 部分信任安全性中讨论的各种安全功能。

另请参阅