Общие сведения о переходах

Windows Presentation Foundation (WPF) поддерживает навигацию в стиле браузера, которую можно использовать в приложениях двух типов: автономные приложения и приложения браузера XAML (XBAP). Чтобы упаковать содержимое для навигации, WPF предоставляет Page класс. Можно осуществлять переход от одного Page к другому декларативно, с помощью Hyperlink или программно с помощью NavigationService . WPF использует журнал для запоминания страниц, которые были перемещены из, и для перехода к ним.

Page, Hyperlink , NavigationService , и журнал образуют основу поддержки навигации, предоставляемой WPF. В этом обзоре подробно рассматриваются эти функции, прежде чем будет рассмотрена поддержка расширенной навигации, включающая навигацию по свободным Язык XAML файлам, ФАЙЛАМ HTML и объектам.

Примечание

В этом разделе термин «браузер» относится только к браузерам, в которых могут размещаться приложения WPF, которые в настоящее время включают в себя Microsoft Internet Explorer и Firefox. Если конкретные функции 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" />

Объект Page , реализованный в XAML разметке, имеет Page как корневой элемент и требует объявления пространства имен XML WPF. 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 Build Engine (MSBuild) создать partial класс, производный от, Page и имеет имя, заданное x:Class атрибутом. Для этого требуется добавить объявление пространства имен XML для XAML схемы ( xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ). Созданный partial класс реализует метод InitializeComponent , который вызывается для регистрации событий и задания свойств, реализованных в разметке.

  • В коде программной части класс должен быть partial классом с тем же именем, который указан x:Class атрибутом в разметке и должен быть производным от класса Page . Это позволяет связать файл кода программной части с partial классом, созданным для файла разметки при сборке приложения (см. раздел Создание приложения WPF).

  • В коде программной части Page класс должен реализовывать конструктор, который вызывает InitializeComponent метод. InitializeComponent реализуется созданным классом файла разметки partial для регистрации событий и задания свойств, определенных в разметке.

Примечание

При добавлении нового Page в проект с помощью Visual Studio объект Page реализуется с помощью разметки и кода программной части и включает необходимую конфигурацию для создания связи между файлами разметки и файлов кода программной части, как описано здесь.

После получения можно Page переходить к нему. Чтобы указать первый Page , к которому приложение переходит, необходимо настроить запуск Page .

Настройка начальной страницы

Для XBAP требуется определенное количество инфраструктуры приложений, размещаемых в браузере. В WPF Application класс является частью определения приложения, которое устанавливает необходимую инфраструктуру приложений (см. Обзор управления приложениями).

Определение приложения обычно реализуется с помощью разметки и кода программной части с файлом разметки, настроенным в качестве ApplicationDefinition элемента MSBuild. Ниже приведено определение приложения для 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 , который Page автоматически загружается при запуске XBAP. Это можно сделать, задав StartupUri свойству универсальный код ресурса (URI) для требуемого значения Page .

Примечание

В большинстве случаев объект Page либо компилируется в приложение, либо развертывается вместе с ним. В этих случаях URI, определяющий, Page — это URI типа "Pack", который соответствует схеме Pack . URI типа "Pack" обсуждаются далее в URI типа " Pack" в WPF. Для перехода к содержимому можно также использовать схему 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 атрибут задается с помощью относительного URI типа Pack, определяющего Homepage. XAML. При запуске XBAP автоматически осуществляется переход на страницу HomePage. XAML и ее отображение. Это продемонстрировано на следующем рисунке, в котором показан XBAP, запущенный с веб-сервера.

XBAP-страница

Примечание

Дополнительные сведения о разработке и развертывании XBAP см. в разделе Общие сведения о приложениях браузера WPF XAML и развертывании приложения WPF.

Настройка заголовка, ширины и высоты основного окна

Первое, что вы могли заметить на предыдущем рисунке, заключается в том, что заголовок в браузере и на панели вкладок является универсальным кодом ресурса (URI) для XBAP. Заголовок не только длинный, но также не является ни привлекательным, ни информативным. По этой причине Page предлагает способ изменить заголовок, задав WindowTitle свойство. Кроме того, можно настроить ширину и высоту окна браузера, установив WindowWidth и WindowHeight соответственно.

WindowTitle, WindowWidth и 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 состоит из нескольких страниц. Самый простой способ перехода с одной страницы на другой — использовать Hyperlink . Можно декларативно добавить Hyperlink в объект, Page используя Hyperlink элемент, который показан в следующей разметке.

<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 элемента требуется следующее:

  • URI типа Pack для Page перехода в, как указано в NavigateUri атрибуте.

  • Содержимое, которое пользователь может щелкнуть для инициации навигации, например текст и изображения (для содержимого, которое Hyperlink может содержать элемент, см. раздел Hyperlink ).

На следующем рисунке показан XBAP с Page Hyperlink .

Страница с гиперссылкой

Как и следовало бы ожидания, нажатие кнопки Hyperlink вызывает переход XBAP к объекту Page , определяемому NavigateUri атрибутом. Кроме того, XBAP добавляет запись для предыдущего Page списка «Последние страницы» в Internet Explorer. Это показано на следующем рисунке.

Кнопки назад и вперед

А также поддержка переходов от одного Page к другому, 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 атрибут должен включать следующее:

  • Универсальный код ресурса (URI) Page с фрагментом содержимого, к которому необходимо выполнить переход.

  • Символ "#".

  • Имя элемента Page , содержащего фрагмент содержимого.

URI фрагмента имеет следующий формат.

URI_страницы # имя_элемента.

Ниже приведен пример 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 события.

Важно!

Можно перейти к фрагментам на несвободных XAML страницах (файлы только разметки XAML с Page корневым элементом), только если страницы можно просматривать по протоколу HTTP.

Однако свободная XAML страница может переходить к собственным фрагментам.

Хотя Hyperlink позволяет пользователю инициировать навигацию по конкретному Page , работа по поиску и скачиванию страницы выполняется NavigationService классом. По сути, NavigationService предоставляет возможность обработки запроса навигации от имени клиентского кода, например Hyperlink . Кроме того, NavigationService реализует поддержку более высокого уровня для отслеживания и влияния на запрос навигации.

При Hyperlink нажатии кнопки WPF вызывает метод, NavigationService.Navigate чтобы нахождение и скачивание по Page указанному URI типа pack. Загруженный файл Page преобразуется в дерево объектов, корневой объект которых является экземпляром скачанного Page . Ссылка на корневой Page объект хранится в NavigationService.Content свойстве. URI типа "Pack" для содержимого, к которому осуществлялся переход, хранится в NavigationService.Source свойстве, а в NavigationService.CurrentSource хранится URI типа "Pack" для последней страницы, к которой был выполнен переход.

Примечание

Приложение WPF может иметь более одного активного в данный момент NavigationService . Дополнительные сведения см. в подразделе узлы навигации далее в этой статье.

Программный переход с помощью службы переходов

Вам не нужно знать о том NavigationService , реализована ли Навигация декларативно в разметке с помощью Hyperlink , поскольку Hyperlink использует от NavigationService вашего имени. Это означает, что, если прямой или непрямой родительский элемент a Hyperlink является узлом навигации (см. раздел навигационные узлы), сможет Hyperlink найти и использовать службу навигации узла навигации для обработки запроса навигации.

Однако существуют ситуации, когда необходимо использовать NavigationService напрямую, включая следующие.

  • Если необходимо создать экземпляр Page с использованием конструктора без параметров.

  • Если необходимо задать свойства для, Page прежде чем переходить к нему.

  • Если нужно выполнить Page Переход к, можно определить только во время выполнения.

В таких ситуациях необходимо написать код для программной инициации навигации путем вызова Navigate метода NavigationService объекта. Для этого требуется получить ссылку на NavigationService .

Получение ссылки на службу переходов

По причинам, описанным в разделе узлы навигации , приложение WPF может иметь более одного NavigationService . Это означает, что вашему коду нужен способ поиска NavigationService , который обычно используется NavigationService для перехода к текущему Page . Чтобы получить ссылку на, можно NavigationService вызвать static NavigationService.GetNavigationService метод. Чтобы получить объект NavigationService , который переходит к определенному объекту Page , в Page качестве аргумента метода передается ссылка GetNavigationService . В следующем коде показано, как получить NavigationService для текущего Page .

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 NavigationService При Page вызове события может получиться только ссылка на него Loaded .

Программный переход к объекту страницы

В следующем примере показано, как использовать NavigationService для программного перехода к 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

Объект Page , который переходит к элементу Page с конструктором без параметров, показан в следующей разметке и коде.

<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 типа pack

Если необходимо создать URI типа "Pack" программным способом (например, при определении URI типа "Pack" во время выполнения), можно использовать 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

Обновление текущей страницы

Объект Page не загружается, если он имеет тот же URI типа Pack, что и URI типа Pack, хранящийся в NavigationService.Source свойстве. Чтобы принудительно загрузить текущую страницу в 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 класс вызывает соответствующее событие. Frame и NavigationWindow предлагают те же события для обнаружения переходов в соответствующих областях.

В некоторых случаях 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. Это показано на следующем рисунке.

Кнопки назад и вперед

Для XBAP, размещенных в Internet Explorer, WPF интегрирует журнал в навигацию по UI Internet Explorer. Это позволяет пользователям перемещаться по страницам в XBAP с помощью кнопок назад, вперед и Последние страницы в Internet Explorer.

Важно!

В Internet Explorer, когда пользователь отключается от XBAP и возвращается к нему, только записи журнала для страниц, которые не были сохранены в активном состоянии, сохраняются в журнале. Сведения о сохранении страниц в активном состоянии см. в разделе время существования страницы и журнал далее в этой статье.

По умолчанию текст Page , отображаемый в списке Последние страницы Internet Explorer, является универсальным кодом ресурса (URI) для Page . В большинстве случаев это не особенно важно для пользователя. К счастью можно изменить текст, используя следующие параметры.

  1. Значение присоединенного JournalEntry.Name атрибута.

  2. Page.TitleЗначение атрибута.

  3. Page.WindowTitleЗначение атрибута и универсальный код ресурса (URI) для текущего Page .

  4. Универсальный код ресурса (URI) для текущего Page . (по умолчанию)

Порядок, в котором перечислены параметры, совпадает с порядком приоритета для поиска текста. Например, если 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. Одной из причин для этого является предоставление пользовательских интерфейсов навигации на страницах.

Можно декларативно добавить поддержку навигации по журналам с помощью команд навигации, предоставляемых 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 с несколькими страницами, содержащими обширное содержимое, включая графику, анимацию и мультимедиа. Объем памяти для подобных страниц может быть довольно большим, особенно если используются видеоматериалы и звуковые файлы. Учитывая, что журнал "запоминает" страницы, к которым был выполнен переход, может быстро использовать большой и заметный объем памяти.

По этой причине поведение журнала по умолчанию заключается в хранении Page метаданных в каждой записи журнала, а не в ссылке на Page объект. При переходе к записи журнала ее Page метаданные используются для создания нового экземпляра указанного объекта Page . Как следствие, каждый Page , к которому осуществляется переход, имеет время существования, показанное на следующем рисунке.

Время существования страницы

Несмотря на то, что использование поведения ведения журнала по умолчанию может сэкономить на потреблении памяти, производительность отрисовки на странице может снизиться; Page при повторном создании экземпляра может потребоваться много времени, особенно если у него много содержимого. Если необходимо хранить Page экземпляр в журнале, можно нарисовать два метода для этого. Во-первых, можно программным путем выполнить переход к Page объекту, вызвав NavigationService.Navigate метод.

Во-вторых, можно указать, что WPF будет хранить экземпляр Page в журнале, задав KeepAlive для свойства значение true (значение по умолчанию — false ). Как показано в следующем примере, можно задать 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 события. Как показано на следующем рисунке, Loaded Unloaded события и по-прежнему создаются каждый раз, когда Page осуществляется переход к и из соответственно.

При генерации событий загрузки и выгрузки

Если 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Переходит обратно к.

WPF автоматически использует эту поддержку при использовании следующих элементов управления в Page :

Если Page компонент использует эти элементы управления, данные, которые они записывают в них, запоминаются по Page переходам, как показано на ListBox следующем рисунке.

Страница с элементами управления, помнящими состояние

Если Page у элемента есть элементы управления, отличные от указанных в приведенном выше списке, или если состояние хранится в пользовательских объектах, необходимо написать код, чтобы журнал запомнил состояние в ходе Page переходов.

Если необходимо запомнить небольшие элементы состояния при Page переходах, можно использовать свойства зависимостей (см DependencyProperty .), настроенные с FrameworkPropertyMetadata.Journal флагом метаданных.

Если ваше состояние, которое необходимо Page Запомнить в переходах, состоит из нескольких фрагментов данных, может оказаться, что для инкапсуляции вашего состояния в один класс и реализации интерфейса будет использоваться меньше кода IProvideCustomContentState .

Если необходимо перемещаться по различным состояниям одного объекта Page , не переходя от Page самого себя, можно использовать IProvideCustomContentState и NavigationService.AddBackEntry .

Файлы cookie

Другой способ, которым приложения WPF могут хранить данные, — это файлы cookie, которые создаются, обновляются и удаляются с помощью SetCookie GetCookie методов и. Файлы cookie, которые можно создать в WPF, — это те же файлы cookie, которые используются другими типами веб-приложений. файлы cookie — это произвольные фрагменты данных, которые хранятся приложением на клиентском компьютере во время или между сеансами приложения. Данные файлов cookie обычно представлены в форме пары "имя — значение" в следующем формате.

Имя = Значение

При передаче данных SetCookie вместе с Uri расположением, для которого должен быть задан файл cookie, файл cookie создается в памяти и доступен только в течение текущего сеанса приложения. Этот тип файлов cookie называется сеансом cookie.

Чтобы сохранить файл cookie на протяжении нескольких сеансов приложения, необходимо добавить в файл cookie дату окончания срока действия, используя следующий формат.

Имя = Значение; expires=DAY, DD-MMM-YYYY HH:MM:SS GMT

Файл cookie с датой окончания срока действия хранится в папке временных файлов временной папки установки Windows до истечения срока действия файла cookie. Такой файл cookie называется постоянным файлом cookie , так как он сохраняется во всех сеансах приложения.

Вы получаете как сеанс, так и постоянные файлы cookie, вызывая GetCookie метод, передав Uri расположение, где файл cookie был задан SetCookie методом.

Ниже приведены некоторые способы поддержки файлов cookie в WPF.

  • Автономные приложения WPF и XBAP могут создавать файлы cookie и управлять ими.

  • Файлы cookie, созданные XBAP, можно получить из браузера.

  • XBAP из одного домена могут создавать файлы cookie и совместно использовать их.

  • XBAP и HTML-страницы из одного домена могут создавать файлы cookie и совместно использовать их.

  • Файлы cookie отправляются, когда XBAP и свободные XAML страницы выполняют веб-запросы.

  • ПРИЛОЖЕНИЯ и приложения XBAP верхнего уровня, размещенные в IFRAME, имеют доступ к файлам cookie.

  • Поддержка файлов cookie в WPF одинакова для всех поддерживаемых браузеров.

  • В Internet Explorer политика P3P, относящаяся к файлам cookie, учитывается WPF, особенно в отношении сторонних разработчиков и XBAP.

Структурная навигация

Если необходимо передать данные из одного Page в другой, можно передать данные в качестве аргументов в конструктор без параметров Page . Обратите внимание, что при использовании этого метода необходимо поддерживать активность. в противном случае при Page следующем переходе к Page WPF повторно создает экземпляр с Page помощью конструктора без параметров.

Кроме того, Page можно реализовать свойства, которые устанавливаются с данными, которые необходимо передать. Однако, когда нужно Page передать данные обратно в объект Page , к которому осуществляется переход. Проблема заключается в том, что Навигация изначально не поддерживает механизмы, гарантирующие, что Page будет возвращено значение после перехода от. По существу переходы не поддерживают семантику вызова/возврата. Для решения этой проблемы WPF предоставляет PageFunction<T> класс, который можно использовать, чтобы гарантировать, что компонент Page возвращается в прогнозируемом и структурированном виде. Дополнительные сведения см. в разделе Общие сведения о структурной навигации.

Класс NavigationWindow

К этому моменту мы рассмотрели целый ряд служб переходов, которые с наибольшей вероятностью будут использоваться для построения приложений с содержимым, допускающим переходы. Эти службы обсуждались в контексте XBAP, хотя они не ограничиваются XBAP. Современные операционные системы и приложения для Windows используют преимущества браузера современных пользователей, чтобы внедрить навигацию в стиле браузера в автономные приложения. Ниже приведены распространенные примеры.

  • Тезаурус: переход по вариантам слов.

  • Обозреватель файлов: переход по файлам и папкам.

  • Мастеры: разбиение сложной задачи на несколько страниц, по которым можно перемещаться. Примером является мастер компонентов Windows, который обрабатывает Добавление и удаление компонентов Windows.

Чтобы включить навигацию в стиле браузера в автономные приложения, можно использовать NavigationWindow класс. NavigationWindow является производным от Window и расширяет его с помощью одной и той же поддержки навигации, предоставляемой XBAP. Можно использовать NavigationWindow в качестве главного окна автономного приложения или вторичного окна, такого как диалоговое окно.

Для реализации NavigationWindow , как и в большинстве классов верхнего уровня в WPF ( Window , Page и т. д.), используется сочетание разметки и кода программной части. Это показано в следующем примере.

<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 , который автоматически переходит на Page страницу (Homepage. XAML) при NavigationWindow открытии. Если NavigationWindow является основным окном приложения, можно использовать StartupUri атрибут для его запуска. Это показано в следующем примере разметки.

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

На следующем рисунке показано в NavigationWindow качестве главного окна автономного приложения.

Главное окно

На рисунке видно, что NavigationWindow имеет заголовок, даже если он не был задан в NavigationWindow коде реализации из предыдущего примера. Вместо этого заголовок задается с помощью WindowTitle свойства, которое показано в следующем коде.

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

Установка WindowWidth свойств и WindowHeight также влияет на NavigationWindow .

Обычно вы реализуете свой собственный, NavigationWindow когда необходимо настроить его поведение или внешний вид. Если вы этого не сделали, можно использовать команду быстрого вызова. Если указать URI типа "Pack" в Page как StartupUri в автономном приложении, Application автоматически создает 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()

На следующем рисунке показан результат.

Диалоговое окно

Как видите, NavigationWindow отображаются кнопки назад и вперед в стиле Internet Explorer, позволяющие пользователям перемещаться по журналу. Эти кнопки предоставляют пользователям те же возможности, что показаны на следующем рисунке.

Кнопки “Дальше” и “Назад” в NavigationWindow

Если страницы предоставляют собственную поддержку навигации по журналам и пользовательский интерфейс, можно скрыть кнопки назад и вперед , выводимые NavigationWindow ShowsNavigationUI свойством, задав для свойства значение false .

Кроме того, можно использовать поддержку настройки в WPF, чтобы заменить UI NavigationWindow саму себя.

Класс Frame

Как браузер, так и NavigationWindow окна, в которых размещается содержимое для навигации. В некоторых случаях приложения имеют содержимое, которое не обязательно должно размещаться в целом окне. Такое содержимое помещается внутрь другого содержимого. Можно вставить содержимое для навигации в другое содержимое с помощью Frame класса. Frame предоставляет такую же поддержку, как NavigationWindow и XBAP.

В следующем примере показано, как добавить Frame к Page декларативно с помощью 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" />
</Page>

Эта разметка задает Source атрибут Frame элемента с URI типа Pack для, Page который Frame должен изначально переходить к. На следующем рисунке показан XBAP с объект, Page имеющий Frame Переход между несколькими страницами.

Фрейм, осуществивший переход по нескольким страницам

Не нужно использовать только Frame внутри содержимого Page . Также обычно размещается Frame внутри содержимого Window .

По умолчанию Frame использует собственный журнал только в отсутствие другого журнала. Если Frame компонент является частью содержимого, размещенного внутри NavigationWindow или XBAP, Frame использует журнал, принадлежащий к NavigationWindow XBAP. Однако иногда Frame может потребоваться ответственный за собственный журнал. Одной из причин для этого является разрешение навигации по журналам на страницах, размещенных в Frame . Это показано на следующем рисунке.

Схема фрейма и страницы

В этом случае можно настроить Frame для использования собственного журнала, задав JournalOwnership для свойства объекта значение Frame OwnsJournal . Это показано в следующем примере разметки.

<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 , который использует собственный журнал.

Фрейм с собственным журналом

Обратите внимание, что записи журнала отображаются навигацией UI в Frame , а не Internet Explorer.

Примечание

Если Frame компонент является частью содержимого, размещенного в Window , Frame использует собственный журнал и, следовательно, отображает собственную навигацию UI .

Если взаимодействие с пользователем требуется Frame для предоставления собственного журнала без отображения навигации UI , можно скрыть навигацию, UI задав для свойства значение NavigationUIVisibility Hidden . Это показано в следующем примере разметки.

<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>

Frame и NavigationWindow являются классами, называемыми узлами навигации. Узел навигации — это класс, который может перейти к содержимому и отобразить его. Для этого каждый узел навигации использует собственные NavigationService журналы и. На следующем рисунке показана основная структура узла переходов.

Схемы перехода

По сути, это позволяет NavigationWindow и Frame предоставлять такую же поддержку навигации, которую предоставляет XBAP при размещении в браузере.

Помимо использования NavigationService и журнала, узлы навигации реализуют те же члены, которые NavigationService реализуют. Это показано на следующем рисунке.

Журнал во фрейме и в NavigationWindow

Это позволяет программировать поддержку переходов непосредственно с ними. Это может быть полезно, если необходимо предоставить пользовательскую навигацию UI для Frame , которая размещена в Window . Более того, оба типа реализуют дополнительные элементы, связанные с навигацией, включая BackStack ( NavigationWindow.BackStack , Frame.BackStack ) и ForwardStack ( NavigationWindow.ForwardStack , Frame.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 из следующих файлов:

  • веб-узел на локальном компьютере, в интрасети или Интернете;

  • Общий файловый ресурс UNC.

  • локальный диск.

Свободный XAML файл можно добавить в Избранное браузера или на домашнюю страницу браузера.

Примечание

Дополнительные сведения о публикации и запуске свободных XAML страниц см. в разделе Развертывание приложения WPF.

Единственное ограничение в отношении свободного XAML : можно разместить только содержимое, которое может быть запущено в режиме частичного доверия. Например, Window не может быть корневым элементом свободного XAML файла. Дополнительные сведения см. в разделе Безопасность частичного доверия в WPF.

Как вы можете ожидать, можно также переходить к HTML. Необходимо просто предоставить универсальный код ресурса (URI), использующий схему HTTP. Например, ниже показано, XAML Frame что выполняет переход на HTML-страницу.

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

Для перехода к HTML требуются специальные разрешения. Например, невозможно выполнить переход от 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

На следующем рисунке показан результат.

Страница, осуществляющая переход в класс

Из этого рисунка можно видеть, что ничего полезного не отобразилось. Фактически отображаемое значение является возвращаемым значением ToString метода для объекта Person ; по умолчанию это единственное значение, которое 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>

Здесь шаблон данных связан с Person типом с помощью x:Type расширения разметки в DataType атрибуте. Затем шаблон данных привязывает TextBlock элементы (см TextBlock .) к свойствам Person класса. На следующем рисунке показан обновленный внешний вид Person объекта.

Переход к классу с шаблоном данных

Преимуществом этого способа является связность, которая обеспечивается возможностью повторного использования шаблона данных для согласованного отображения объектов в любом месте приложения.

Дополнительные сведения о шаблонах данных см. в разделе Общие сведения о создании шаблонов данных.

Безопасность

Поддержка навигации в WPF позволяет переходить к XBAP через Интернет, что позволяет приложениям размещать сторонние материалы. Для защиты приложений и пользователей от вредоносного поведения WPF предоставляет разнообразные функции безопасности, обсуждаемые в разделе Безопасность и Безопасность частичного доверия в WPF.

См. также раздел