Compartilhar via


Visão geral da navegação

O Windows Presentation Foundation (WPF) dá suporte à navegação no estilo navegador que pode ser usada em dois tipos de aplicativos: aplicativos autônomos e XBAPs (aplicativos do navegador XAML). Para empacotar conteúdo para navegação, o WPF fornece a Page classe. Você pode navegar de um Page para outro declarativamente, usando um Hyperlink, ou programaticamente, usando o NavigationService. O WPF usa o diário para lembrar as páginas que foram navegadas e retornar a elas.

Page, Hyperlinke NavigationServiceo diário formam o núcleo do suporte de navegação oferecido pelo WPF. Essa visão geral explora esses recursos em detalhes antes de abranger o suporte avançado de navegação que inclui navegação para arquivos XAML (Extensible Application Markup Language), arquivos HTML e objetos.

Observação

Neste tópico, o termo "navegador" refere-se apenas a navegadores que podem hospedar aplicativos WPF, que atualmente incluem o Microsoft Internet Explorer e o Firefox. Quando recursos específicos do WPF têm suporte apenas por um navegador específico, a versão do navegador é referenciada.

Este tópico fornece uma visão geral dos principais recursos de navegação no WPF. Esses recursos estão disponíveis para aplicativos autônomos e XBAPs, embora este tópico os apresente no contexto de um XBAP.

Observação

Este tópico não discute como criar e implantar XBAPs. Para obter mais informações sobre XBAPs, consulte a visão geral dos aplicativos do navegador XAML do WPF.

Esta seção explica e demonstra os seguintes aspectos da navegação:

Implementando uma página

No WPF, você pode navegar até vários tipos de conteúdo que incluem objetos do .NET Framework, objetos personalizados, valores de enumeração, controles de usuário, arquivos XAML e arquivos HTML. No entanto, você descobrirá que a maneira mais comum e conveniente de empacotar conteúdo é usando Page. Além disso, Page implementa recursos específicos de navegação para aprimorar sua aparência e simplificar o desenvolvimento.

Usando Page, você pode implementar declarativamente uma página navegável de conteúdo XAML usando marcação como a seguinte.

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

Um Page que é implementado na marcação XAML tem Page como elemento raiz e requer a declaração de namespace XML do WPF. O Page elemento contém o conteúdo para o qual você deseja navegar e exibir. Adicione conteúdo definindo o Page.Content elemento de propriedade, conforme mostrado na marcação a seguir.

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

Page.Content só pode conter um elemento filho; no exemplo anterior, o conteúdo é uma única cadeia de caracteres, "Olá, Página!" Na prática, você geralmente usará um controle de layout como o elemento filho (consulte Layout) para conter e compor seu conteúdo.

Os elementos filho de um Page elemento são considerados o conteúdo de um Page e, consequentemente, você não precisa usar a declaração explícita Page.Content . A marcação a seguir é o equivalente declarativo ao exemplo anterior.

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

Nesse caso, Page.Content é definido automaticamente com os elementos filho do Page elemento. Para obter mais informações, consulte o Modelo de Conteúdo do WPF.

Uma marcação somente Page é útil para exibir conteúdo. No entanto, um Page também pode exibir controles que permitem aos usuários interagir com a página e pode responder à interação do usuário tratando de eventos e chamando a lógica de aplicação. Um interativo Page é implementado usando uma combinação de marcação e code-behind, conforme mostrado no exemplo a seguir.

<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

Para permitir que um arquivo de marcação e um arquivo code-behind funcionem juntos, a seguinte configuração é necessária:

  • Na marcação, o Page elemento deve incluir o x:Class atributo. Quando o aplicativo é criado, a existência de x:Class no arquivo de marcação faz com que o mecanismo de build da Microsoft (MSBuild) crie uma classe partial que deriva de Page e tem o nome especificado pelo atributo x:Class. Isso requer a adição de uma declaração de namespace XML para o esquema XAML ( xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ). A classe gerada partial implementa InitializeComponent, que é chamada para registrar os eventos e definir as propriedades que são implementadas na marcação.

  • No code-behind, a classe deve ser uma partial classe com o mesmo nome especificado pelo atributo x:Class no markup, e deve derivar de Page. Isso permite que o arquivo code-behind seja associado à partial classe que é gerada para o arquivo de marcação quando o aplicativo é criado (consulte Como criar um aplicativo WPF).

  • No code-behind, a classe Page deve implementar um construtor que chame o método InitializeComponent. InitializeComponent é implementado pela classe gerada partial do arquivo de marcação para registrar eventos e definir propriedades definidas na marcação.

Observação

Quando você adiciona um novo Page ao seu projeto usando o Visual Studio, o Page é implementado usando tanto a marcação quanto o code-behind e inclui a configuração necessária para criar a associação entre os arquivos de marcação e code-behind, conforme descrito aqui.

Depois de ter um Page, você poderá navegar até ele. Para especificar o primeiro Page para o qual um aplicativo navega, você precisa configurar o início Page.

Configurando uma página inicial

Os XBAPs exigem que uma determinada quantidade de infraestrutura de aplicativo seja hospedada em um navegador. No WPF, a Application classe faz parte de uma definição de aplicativo que estabelece a infraestrutura de aplicativo necessária (consulte a Visão geral do Gerenciamento de Aplicativos).

Uma definição de aplicativo geralmente é implementada usando markup e code-behind, com o arquivo de markup configurado como um item do MSBuildApplicationDefinition . Veja a seguir uma definição de aplicativo para um 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

Um XBAP pode usar sua definição de aplicativo para especificar um início Page, que é o Page carregado automaticamente quando o XBAP é iniciado. Defina a propriedade StartupUri com o identificador uniforme de recursos (URI) do Page desejado.

Observação

Na maioria dos casos, o Page é compilado ou implantado com um aplicativo. Nesses casos, o URI que identifica Page é um URI de pacote, que está em conformidade com o esquema pack. As URIs do pacote são discutidas ainda mais nas URIs do Pacote no WPF. Você também pode navegar até o conteúdo usando o esquema http, que é discutido abaixo.

Você pode definir StartupUri declarativamente na marcação, conforme mostrado no exemplo a seguir.

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

Neste exemplo, o StartupUri atributo é definido com um URI de pacote relativo que identifica HomePage.xaml. Quando o XBAP é iniciado, é automaticamente redirecionado para HomePage.xaml e esta é exibida. Isso é demonstrado pela figura a seguir, que mostra um XBAP que foi iniciado a partir de um servidor Web.

Página XBAP

Observação

Para obter mais informações sobre o desenvolvimento e a implantação de XBAPs, consulte a visão geral dos aplicativos do navegador XAML do WPF e a implantação de um aplicativo WPF.

Configurando o título, a largura e a altura da janela do host

Algo que você pode ter percebido na figura anterior é que o título do navegador e do painel de abas é o URI do XBAP. Além de ser longo, o título não é atraente nem informativo. Por esse motivo, Page oferece uma maneira de alterar o título definindo a WindowTitle propriedade. Além disso, você pode configurar a largura e a altura da janela do navegador definindo WindowWidth e WindowHeight, respectivamente.

WindowTitle, WindowWidthe WindowHeight pode ser definido declarativamente na marcação, conforme mostrado no exemplo a seguir.

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

O resultado é mostrado na figura a seguir.

Título da janela, altura, largura

Um XBAP típico é composto por várias páginas. A maneira mais simples de navegar de uma página para outra é usar uma Hyperlink. Você pode adicionar declarativamente um Hyperlink a um Page usando o Hyperlink elemento, que é mostrado na marcação a seguir.

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

Um Hyperlink elemento requer o seguinte:

  • O URI do pacote de Page para o qual navegar, conforme especificado pelo atributo NavigateUri.

  • Conteúdo que um usuário pode clicar para iniciar a navegação, como texto e imagens (para o conteúdo que o Hyperlink elemento pode conter, consulte Hyperlink).

A figura a seguir mostra um XBAP com um Page que tem um Hyperlink.

Página com Hiperlink

Como seria de esperar, clicar nas Hyperlink faz com que o XBAP navegue até o Page identificado pelo atributo NavigateUri. Além disso, o XBAP adiciona uma entrada para o anterior Page à lista Páginas Recentes no Internet Explorer. Isso será mostrado na figura a seguir.

Os botões Voltar e Avançar

Além de dar suporte à navegação de um Page para o outro, Hyperlink também dá suporte à navegação de fragmentos.

Navegação de fragmentos

A navegação por fragmentos é a navegação para um fragmento de conteúdo no atual Page ou em outro Page. No WPF, um fragmento de conteúdo é o conteúdo contido por um elemento nomeado. Um elemento nomeado é um elemento que tem seu Name conjunto de atributos. A marcação a seguir mostra um elemento nomeado TextBlock que contém um fragmento de conteúdo.

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

Para que um Hyperlink usuário navegue até um fragmento de conteúdo, o NavigateUri atributo deve incluir o seguinte:

  • O URI do Page fragmento com o conteúdo para o qual navegar.

  • Um caractere "#".

  • O nome do elemento no Page que contém o fragmento de conteúdo.

Um URI de fragmento tem o seguinte formato.

PageURI#ElementName

O exemplo a seguir mostra um exemplo de um Hyperlink que está configurado para navegar até um fragmento de conteúdo.

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

Observação

Esta seção descreve a implementação de navegação de fragmento padrão no WPF. O WPF também permite que você implemente seu próprio esquema de navegação por fragmentos, que, em parte, requer o tratamento do evento NavigationService.FragmentNavigation.

Importante

Você pode acessar fragmentos em páginas XAML independentes (arquivos XAML contendo apenas marcação com Page como elemento raiz) somente se as páginas estiverem acessíveis via HTTP.

No entanto, uma página XAML solta pode navegar até seus próprios fragmentos.

Embora Hyperlink permita que um usuário inicie a navegação em um determinado Page, o trabalho de localizar e baixar a página é executado pela NavigationService classe. Essencialmente, NavigationService fornece a capacidade de processar uma solicitação de navegação em nome do código do cliente, como o Hyperlink. Além disso, NavigationService implementa o suporte de nível superior para acompanhar e influenciar uma solicitação de navegação.

Quando um Hyperlink é clicado, o WPF chama NavigationService.Navigate para localizar e baixar o Page no pack URI especificado. O Page baixado é convertido em uma árvore de objetos cujo objeto raiz é uma instância do Page baixado. Uma referência ao objeto raiz Page é armazenada na NavigationService.Content propriedade. O URI do pacote para o conteúdo que foi navegado é armazenado na propriedade NavigationService.Source, enquanto a propriedade NavigationService.CurrentSource armazena o URI do pacote para a última página que foi navegada.

Observação

É possível que um aplicativo WPF tenha mais de um ativo NavigationServiceno momento. Para obter mais informações, consulte Hosts de Navegação mais adiante neste tópico.

Navegação programática com o Serviço de Navegação

Você não precisa saber sobre NavigationService se a navegação é implementada declarativamente na marcação usando Hyperlink, porque Hyperlink usa o NavigationService em seu lugar. Isso significa que, desde que o pai direto ou indireto de um Hyperlink seja um host de navegação (consulte Hosts de Navegação), Hyperlink poderá localizar e usar o serviço de navegação do host de navegação para processar uma solicitação de navegação.

No entanto, há situações em que você precisa usar NavigationService diretamente, incluindo o seguinte:

  • Quando você precisa criar uma Page instância usando um construtor sem parâmetros.

  • Quando você precisa definir propriedades no Page antes de navegar até ele.

  • Quando o Page que precisa ser navegado só pode ser determinado em tempo de execução.

Nessas situações, você precisa escrever código para iniciar a navegação programaticamente chamando o Navigate método do NavigationService objeto. Isso requer a obtenção de uma referência a um NavigationService.

Obtendo uma referência ao NavigationService

Por motivos abordados na seção Hosts de Navegação , um aplicativo WPF pode ter mais de um NavigationService. Isso significa que seu código precisa de uma maneira de encontrar um NavigationService, que geralmente é o NavigationService que navega para o atual Page. Você pode obter uma referência a um NavigationService chamando o staticNavigationService.GetNavigationService método. Para obter o NavigationService que navegou para um determinado Page, passe uma referência ao Page como argumento do método GetNavigationService. O código a seguir mostra como obter o NavigationService para o atual 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)

Como um atalho para localizar o NavigationService para um Page, Page implementa a propriedade NavigationService. Isso é mostrado no exemplo a seguir.

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

Observação

Uma Page só pode obter uma referência à sua NavigationService quando Page aciona o evento Loaded.

Navegação programática para um objeto de página

O exemplo a seguir mostra como usar o NavigationService para navegar programaticamente até um Page. A navegação programática é necessária porque o Page para o qual está sendo navegado só pode ser instanciado usando um único construtor que não é sem parâmetros. O Page construtor sem parâmetros é mostrado na marcação e no código a seguir.

<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

O Page que navega até o Page com um construtor que não é sem parâmetros é mostrado na marcação e no código a seguir.

<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

Quando o Hyperlink neste Page é clicado, a navegação é iniciada instanciando o Page para navegar usando o construtor com parâmetros e chamando o método NavigationService.Navigate. Navigate aceita uma referência ao objeto para o qual ele NavigationService navegará, em vez de um URI de pacote.

Navegação programática com um URI de pacote

Se você precisar construir um URI de pacote programaticamente (quando puder determinar apenas o URI do pacote em tempo de execução, por exemplo), poderá usar o NavigationService.Navigate método. Isso é mostrado no exemplo a seguir.

<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

Atualizando a página atual

Um Page não será baixado se ele tiver o mesmo URI do pacote que o URI do pacote armazenado na NavigationService.Source propriedade. Para forçar o WPF a baixar a página atual novamente, você pode chamar o NavigationService.Refresh método, conforme mostrado no exemplo a seguir.

<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

Há muitas maneiras de iniciar a navegação, como você viu. Quando a navegação é iniciada e, enquanto a navegação está em andamento, você pode acompanhar e influenciar a navegação usando os seguintes eventos que são implementados por NavigationService:

  • Navigating. Ocorre quando uma nova navegação é solicitada. Pode ser usado para cancelar a navegação.

  • NavigationProgress. Ocorre periodicamente durante um download para fornecer informações de progresso de navegação.

  • Navigated. Ocorre quando a página foi localizada e baixada.

  • NavigationStopped. Ocorre quando a navegação é interrompida (chamando StopLoading) ou quando uma nova navegação é solicitada enquanto uma navegação atual está em andamento.

  • NavigationFailed. Ocorre quando um erro é gerado durante a navegação até o conteúdo solicitado.

  • LoadCompleted. Ocorre quando o conteúdo que foi navegado é carregado e analisado e começa a ser renderizado.

  • FragmentNavigation. Ocorre quando a navegação para um fragmento de conteúdo começa, o que acontece:

    • Imediatamente, se o fragmento desejado estiver no conteúdo atual.

    • Depois que o conteúdo de origem tiver sido carregado, se o fragmento desejado estiver em conteúdo diferente.

Os eventos de navegação são levantados na ordem ilustrada pelo diagrama a seguir.

Gráfico de fluxograma de navegação da página

Em geral, um Page não está preocupado com esses eventos. É mais provável que um aplicativo esteja preocupado com eles e, por esse motivo, esses eventos também são gerados pela Application classe:

NavigationService Sempre que gera um evento, a Application classe aciona o evento correspondente. Frame e NavigationWindow oferecem os mesmos eventos para detectar a navegação dentro de seus respectivos escopos.

Em alguns casos, um Page pode estar interessado nesses eventos. Por exemplo, um Page pode manipular o evento NavigationService.Navigating para determinar se deseja ou não cancelar a navegação longe de si mesmo. Isso é mostrado no exemplo a seguir.

<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

Se você registrar um manipulador com um evento de navegação de um Page, como demonstra o exemplo anterior, também deverá cancelar o registro do manipulador de eventos. Se você não fizer isso, pode haver efeitos colaterais em relação à forma como a navegação do WPF se lembra Page da navegação usando o histórico.

Lembrando da navegação com o Diário de bordo

O WPF usa duas pilhas para lembrar as páginas pelas quais você navegou: uma pilha de back e uma pilha de forward. Quando você navega da corrente Page para uma nova Page ou para a frente para uma existente Page, a corrente Page é adicionada à pilha traseira. Quando você retorna do estado atual Page para o anterior Page, o atual Page é adicionado à pilha de encaminhamento. A pilha traseira, a pilha para frente e a funcionalidade para gerenciá-las são coletivamente conhecidas como o diário. Cada item na pilha traseira e na pilha de encaminhamento é uma instância da JournalEntry classe e é conhecido como uma entrada de diário.

Conceitualmente, o diário opera da mesma maneira que os botões Voltar e Encaminhar no Internet Explorer. Eles são mostrados na figura a seguir.

Os botões Voltar e Avançar

Para XBAPs hospedados pelo Internet Explorer, o WPF integra o diário à interface do usuário de navegação do Internet Explorer. Isso permite que os usuários naveguem por páginas em um XBAP usando os botões Voltar, Encaminhar e Páginas Recentes no Internet Explorer.

Importante

No Internet Explorer, quando um usuário sai e retorna para um XBAP, somente as entradas de histórico para páginas que não foram mantidas vivas são retidas no histórico. Para discussão sobre como manter as páginas ativas, consulte Page Lifetime e o Journal mais adiante neste tópico.

Por padrão, o texto de cada Page que aparece na lista Páginas Recentes do Internet Explorer é o URI do Page. Em muitos casos, isso não é particularmente significativo para o usuário. Felizmente, você pode alterar o texto usando uma das seguintes opções:

  1. O valor do atributo associado JournalEntry.Name.

  2. O valor do Page.Title atributo.

  3. O valor do atributo Page.WindowTitle e o URI para o atual Page.

  4. O URI para o atual Page. (Padrão)

A ordem na qual as opções são listadas corresponde à ordem de precedência para localizar o texto. Por exemplo, se JournalEntry.Name for definido, os outros valores serão ignorados.

O exemplo a seguir usa o Page.Title atributo para alterar o texto que aparece para uma entrada de diário.

<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

Embora um usuário possa navegar pelo diário usando as páginas Voltar, Encaminhar e Páginas Recentes no Internet Explorer, você também pode navegar pelo diário usando mecanismos declarativos e programáticos fornecidos pelo WPF. Um motivo para fazer isso é fornecer UIs de navegação personalizadas em suas páginas.

Você pode adicionar declarativamente o suporte para navegação em diários usando os comandos de navegação expostos por NavigationCommands. O exemplo a seguir demonstra como usar o BrowseBack comando de navegação.

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

Você pode navegar programaticamente pelo diário usando um dos seguintes membros da NavigationService classe:

O diário também pode ser manipulado programaticamente, conforme discutido na retenção do estado de conteúdo com o histórico de navegação posteriormente neste tópico.

Tempo de vida da página e o diário

Considere um XBAP com várias páginas que contêm conteúdo avançado, incluindo elementos gráficos, animações e mídia. O volume de memória para páginas como essas pode ser bastante grande, especialmente se as mídias de áudio e vídeo forem usadas. Dado que o registro "se lembra" de páginas que foram visitadas, tal XBAP poderia consumir rapidamente uma grande e perceptível quantidade de memória.

Por esse motivo, o comportamento padrão do diário é armazenar Page metadados em cada entrada de diário em vez de uma referência a um Page objeto. Quando uma entrada de diário é acessada, seus Page metadados são usados para criar uma nova instância do especificado Page. Como consequência, cada Page que é navegado tem a duração ilustrada pela figura a seguir.

Tempo de vida da

Embora o uso do comportamento de diário padrão possa economizar no consumo de memória, o desempenho de renderização por página pode ser reduzido; reinstalar um Page pode ser demorado, especialmente se ele tiver muito conteúdo. Se você precisar manter uma Page instância no diário, poderá usar duas técnicas para fazer isso. Primeiro, você pode navegar programaticamente até um Page objeto chamando o NavigationService.Navigate método.

Em segundo lugar, você pode especificar que o WPF retenha uma instância de um Page no histórico ao definir a propriedade KeepAlive como true (o padrão é false). Conforme mostrado no exemplo a seguir, você pode definir KeepAlive declarativamente na marcação.

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

A duração de um Page que é mantido vivo é sutilmente diferente de uma que não é. A primeira vez que um Page que é mantido vivo é acessado, ele é instanciado da mesma forma que um Page que não é mantido vivo. No entanto, como uma instância do Page é mantida no diário, ela nunca será instanciada novamente enquanto permanecer no diário. Consequentemente, se um Page tiver lógica de inicialização que precisa ser chamada sempre que o Page for navegado para, você deverá movê-la do construtor para um manipulador do evento Loaded. Conforme mostrado na figura a seguir, os eventos Loaded e Unloaded ainda são gerados sempre que um Page é navegado para e de, respectivamente.

Quando os eventos Carregados e Descarregados são gerados

Quando um Page não é mantido vivo, você não deve seguir nenhum dos procedimentos a seguir:

  • Armazene uma referência a ela ou qualquer parte dela.

  • Registre manipuladores de eventos com eventos que não são implementados por ele.

Fazer qualquer uma delas criará referências que forcem o Page a ser retido na memória, mesmo depois de ter sido removido do diário.

Em geral, você deve preferir o comportamento padrão Page de não manter um Page ativo. No entanto, isso tem implicações de estado que são discutidas na próxima seção.

Manter o estado de conteúdo usando o histórico de navegação

Se um Page não for mantido ativo e tiver controles que coletam dados do usuário, o que acontecerá com os dados se um usuário navegar para longe e voltar para o Page? Do ponto de vista da experiência do usuário, o usuário deve esperar ver os dados inseridos anteriormente. Infelizmente, como uma nova instância da Page é criada com cada navegação, os controles que coletaram os dados são reinicializados e os dados são perdidos.

Felizmente, o jornal oferece suporte para armazenar dados entre Page navegações, incluindo dados de controle. Especificamente, a entrada de diário para cada Page atua como um contêiner temporário para o estado Page associado. As etapas a seguir descrevem como esse suporte é usado quando se navega a partir de um Page:

  1. Uma entrada para o atual Page é adicionada ao diário.

  2. O estado do Page é armazenado com a entrada de diário para essa página, que é adicionada à pilha de retorno.

  3. O novo Page é navegado para.

Quando se retorna à página Page por meio do diário, as seguintes etapas ocorrem:

  1. A Page (a entrada do diário no topo da pilha) é instanciada.

  2. O Page é atualizado com o estado armazenado no registro do diário para o Page.

  3. O Page é navegado de volta para.

O WPF usa esse suporte automaticamente quando os seguintes controles são usados em um Page:

Se um Page usar esses controles, os dados inseridos neles serão lembrados entre Page navegaçãos, conforme demonstrado pela CorListBox Favorita na figura a seguir.

Página com controles que lembram o estado

Quando um Page tem controles diferentes daqueles da lista anterior ou quando o estado é armazenado em objetos personalizados, você precisa escrever código para fazer com que o diário lembre-se do estado entre as Page navegações.

Se você precisar se lembrar de pequenos fragmentos de estado entre Page navegações, você pode usar propriedades de dependência (veja DependencyProperty) configuradas com o sinalizador de metadados FrameworkPropertyMetadata.Journal.

Se o estado que seu Page precisa lembrar entre as navegações for composto por várias partes de dados, você poderá achar menos intensivo de código encapsular seu estado em uma única classe e implementar a interface IProvideCustomContentState.

Se você precisar navegar por vários estados de um único Page, sem sair do próprio Page, você pode usar IProvideCustomContentState e NavigationService.AddBackEntry.

Biscoitos

Outra maneira que os aplicativos WPF podem armazenar dados é com cookies, que são criados, atualizados e excluídos usando os métodos SetCookie e GetCookie. Os cookies que você pode criar no WPF são os mesmos cookies que outros tipos de aplicativos Web usam; os cookies são partes arbitrárias de dados armazenados por um aplicativo em um computador cliente durante ou entre sessões de aplicativo. Os dados de cookie normalmente assumem a forma de um par nome/valor no formato a seguir.

Nome=Valor

Quando os dados são passados para SetCookie, juntamente com o Uri local para o qual o cookie deve ser definido, um cookie é criado na memória e só está disponível durante a sessão do aplicativo atual. Esse tipo de cookie é conhecido como um cookie de sessão.

Para armazenar um cookie entre sessões de aplicativo, uma data de validade deve ser adicionada ao cookie, usando o formato a seguir.

NOME=VALOR; expires=DAY, DD-MMM-YYYY HH:MM:SS GMT

Um cookie com uma data de validade é armazenado na pasta arquivos temporários da Internet da instalação do Windows até que o cookie expire. Esse cookie é conhecido como um cookie persistente porque ele persiste entre sessões de aplicativo.

Para recuperar cookies de sessão e persistentes, você precisa chamar o método GetCookie, passando o local Uri onde o cookie foi definido com o método SetCookie.

Veja a seguir algumas das maneiras pelas quais os cookies têm suporte no WPF:

  • Aplicativos autônomos do WPF e XBAPs podem criar e gerenciar cookies.

  • Os cookies criados por um XBAP podem ser acessados no navegador.

  • XBAPs do mesmo domínio podem criar e compartilhar cookies.

  • Páginas XBAPs e HTML do mesmo domínio podem criar e compartilhar cookies.

  • Os cookies são expedidos quando XBAPs e páginas XAML soltas fazem solicitações da Web.

  • XBAPs de nível superior e XBAPs hospedados no IFRAMES podem acessar cookies.

  • O suporte a cookie no WPF é o mesmo para todos os navegadores com suporte.

  • No Internet Explorer, a política P3P relativa a cookies é respeitada pelo WPF, particularmente em relação aos XBAPs de primeira e de terceiros.

Navegação estruturada

Se você precisar passar dados de um Page para outro, poderá passar os dados como argumentos para um construtor não sem parâmetros do Page. Observe que, se você usar essa técnica, deverá manter o Page ativo; caso contrário, na próxima vez que navegar até o Page, o WPF reinstancia o Page com o construtor sem parâmetros.

Como alternativa, Page pode implementar propriedades que são definidas pelos dados que precisam ser passados. As coisas se tornam complicadas, no entanto, quando Page é necessário passar dados de volta para o Page que navegou até isso. O problema é que a navegação não dá suporte nativo a mecanismos para garantir que um Page será retornado depois que ele for navegado. Essencialmente, a navegação não dá suporte à semântica de chamada/retorno. Para resolver esse problema, o WPF fornece a PageFunction<T> classe que você pode usar para garantir que um Page seja retornado de forma previsível e estruturada. Para obter mais informações, consulte Visão geral da navegação estruturada.

A classe NavigationWindow

Até agora, você viu a gama de serviços de navegação que você provavelmente usará para criar aplicativos com conteúdo navegável. Esses serviços foram discutidos no contexto dos XBAPs, embora não estejam limitados a XBAPs. Os sistemas operacionais modernos e os aplicativos do Windows aproveitam a experiência do navegador dos usuários modernos para incorporar a navegação no estilo navegador em aplicativos autônomos. Exemplos comuns incluem:

  • Dicionário de sinônimos do Word: navegue pelas opções de palavras.

  • Explorador de Arquivos: navegue por arquivos e pastas.

  • Assistentes: dividir uma tarefa complexa em várias páginas que podem ser navegadas entre elas. Um exemplo é o Assistente de Componentes do Windows que lida com a adição e remoção de recursos do Windows.

Para incorporar a navegação no estilo navegador em seus aplicativos autônomos, você pode usar a NavigationWindow classe. NavigationWindow deriva de Window e o estende com o mesmo suporte para navegação que os XBAPs fornecem. Você pode usar NavigationWindow como a janela principal do aplicativo autônomo ou como uma janela secundária, como uma caixa de diálogo.

Para implementar uma NavigationWindow classe de nível superior, como ocorre com a maioria das classes de nível superior no WPF (Window, Page e assim por diante), use uma combinação de marcação e code-behind. Isso é mostrado no exemplo a seguir.

<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

Esse código cria um NavigationWindow que navega automaticamente para um Page (HomePage.xaml) quando ele NavigationWindow é aberto. Se for a NavigationWindow janela principal do aplicativo, você poderá usar o StartupUri atributo para iniciá-lo. Isso é mostrado na marcação a seguir.

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

A figura a seguir mostra a NavigationWindow janela principal de um aplicativo autônomo.

Uma janela principal

Na figura, você pode ver que o NavigationWindow tem um título, mesmo que não tenha sido configurado no código de implementação do exemplo anterior. Em vez disso, o título é definido usando a WindowTitle propriedade, que é mostrada no código a seguir.

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

Configurar as propriedades WindowWidth e WindowHeight também afeta o NavigationWindow.

Normalmente, você implementa seu próprio NavigationWindow quando precisa personalizar seu comportamento ou sua aparência. Se você não fizer nenhum dos dois, poderá usar um atalho. Se você especificar o URI do pacote de um Page como StartupUri em um aplicativo autônomo, Application criará automaticamente um NavigationWindow para hospedar o Page. A marcação a seguir mostra como habilitar isso.

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

Se você quiser que uma janela de aplicativo secundária, como uma caixa de diálogo, seja uma NavigationWindow, use o código no exemplo a seguir para abri-lo.

// 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()

A figura a seguir mostra o resultado.

Uma caixa de diálogo

Como você pode ver, NavigationWindow exibe os botões Back and Forward , estilo Internet Explorer, que permitem que os usuários naveguem pelo diário. Esses botões fornecem a mesma experiência do usuário, conforme mostrado na figura a seguir.

Botões Voltar e Avançar em uma NavigationWindow

Se suas páginas fornecerem seu próprio suporte de navegação de diário e interface do usuário, você poderá ocultar os botões Voltar e Encaminhar exibidos NavigationWindow definindo o valor da ShowsNavigationUI propriedade como false.

Como alternativa, você pode usar o suporte de personalização no WPF para substituir a interface do usuário de NavigationWindow si mesmo.

A classe Frame

O navegador e NavigationWindow são janelas que hospedam conteúdo navegável. Em alguns casos, os aplicativos têm conteúdo que não precisa ser hospedado por uma janela inteira. Em vez disso, esse conteúdo será hospedado dentro de outro conteúdo. Você pode inserir conteúdo navegável em outro conteúdo usando a Frame classe. Frame fornece o mesmo suporte que NavigationWindow XBAPs e XBAPs.

O exemplo a seguir mostra como adicionar um a um FramePage declarativamente usando o Frame elemento.

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

Essa marcação define o atributo Source do elemento Frame com um URI de pacote para o qual o Page deve navegar inicialmente. A figura a seguir mostra um XBAP com um Page que possui um Frame que navegou entre várias páginas.

Um quadro que navegou entre várias páginas

Você não precisa usar Frame apenas dentro do conteúdo de um Page. Também é comum hospedar um Frame dentro do conteúdo de um Window.

Por padrão, Frame só usa seu próprio diário na ausência de outro diário. Se Frame fizer parte do conteúdo hospedado dentro de um NavigationWindow ou de um XBAP, Frame usa o diário que pertence ao NavigationWindow ou ao XBAP. Às vezes, porém, um Frame pode precisar ser responsável por seu próprio diário. Um motivo para fazer isso é permitir a navegação entre as páginas do diário hospedadas por um Frame. Isso é ilustrado pela figura a seguir.

Diagrama de quadro e página

Nesse caso, você pode configurar o Frame para usar seu próprio diário, definindo a propriedade JournalOwnership de Frame para OwnsJournal. Isso é mostrado na marcação a seguir.

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

A figura a seguir ilustra o efeito de navegar dentro de um Frame que usa seu próprio diário.

Um quadro que usa seu próprio diário

Observe que as entradas de diário são mostradas pela interface do usuário de navegação no Frame, em vez de pelo Internet Explorer.

Observação

Se Frame fizer parte do conteúdo hospedado em um Window, Frame usará seu próprio diário e, consequentemente, exibirá sua própria interface de navegação.

Se a experiência do usuário exigir um diário próprio de Frame sem mostrar a interface de navegação do usuário, você poderá ocultar a interface de navegação do usuário definindo NavigationUIVisibility como Hidden. Isso é mostrado na marcação a seguir.

<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 e NavigationWindow são classes conhecidas como hosts de navegação. Um host de navegação é uma classe que pode navegar e exibir conteúdo. Para fazer isso, cada host de navegação usa seu próprio NavigationService e registro. A construção básica de um host de navegação é mostrada na figura a seguir.

Diagramas do navegador

Essencialmente, isso permite que NavigationWindow e Frame forneçam o mesmo suporte de navegação que um XBAP oferece quando hospedado no navegador.

Além de usar NavigationService e um registro, os hosts de navegação implementam os mesmos membros que NavigationService implementa. Isso é ilustrado pela figura a seguir.

Um jornal em um Quadro e em uma Janela de Navegação

Isso permite que você programe o suporte de navegação diretamente contra eles. Você pode considerar isso se precisar fornecer uma interface do usuário de navegação personalizada para uma Frame hospedada em um Window. Além disso, ambos os tipos implementam membros adicionais relacionados à navegação, incluindo BackStack (NavigationWindow.BackStack, Frame.BackStack) e ForwardStack (NavigationWindow.ForwardStack, Frame.ForwardStack), que permitem enumerar as entradas de histórico na pilha de retrocesso e na pilha de avanço, respectivamente.

Conforme mencionado anteriormente, mais de um diário pode existir em um aplicativo. A figura a seguir fornece um exemplo de quando isso pode acontecer.

Vários diários em um aplicativo

Ao longo deste tópico, Page e os XBAPs de pacote foram usados para demonstrar os vários recursos de navegação do WPF. No entanto, um Page compilado em um aplicativo não é o único tipo de conteúdo que pode ser navegado e os XBAPs do pacote não são a única maneira de identificar o conteúdo.

Como esta seção demonstra, você também pode navegar até arquivos XAML soltos, arquivos HTML e objetos.

Um arquivo XAML flexível é um arquivo com as seguintes características:

  • Contém apenas XAML (ou seja, nenhum código).

  • Tem uma declaração de namespace apropriada.

  • Tem a extensão de nome de arquivo .xaml.

Por exemplo, considere o conteúdo a seguir armazenado como um arquivo XAML solto, 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>

Quando você clica duas vezes no arquivo, o navegador é aberto e navega até e exibe o conteúdo. Isso será mostrado na figura a seguir.

A exibição do conteúdo no arquivo Person.XAML

Você pode exibir um arquivo XAML solto do seguinte:

  • Um site no computador local, na intranet ou na Internet.

  • Um compartilhamento de arquivos na Convenção Universal de Nomenclatura (UNC).

  • O disco local.

Um arquivo XAML solto pode ser adicionado aos favoritos do navegador ou ser a home page do navegador.

Observação

Para obter mais informações sobre como publicar e iniciar páginas XAML soltas, consulte Implantando um aplicativo WPF.

Uma limitação em relação ao XAML flexível é que você só pode hospedar conteúdo seguro para ser executado em confiança parcial. Por exemplo, Window não pode ser o elemento raiz de um arquivo XAML solto. Para obter mais informações, consulte segurança de confiança parcial do WPF.

Como você pode esperar, você também pode navegar até HTML. Você simplesmente precisa fornecer um URI que use o esquema http. Por exemplo, o XAML a seguir mostra um Frame que navega até uma página HTML.

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

Navegar para HTML requer permissões especiais. Por exemplo, você não pode navegar de um XBAP em execução na área restrita de segurança de confiança parcial da zona da Internet. Para obter mais informações, consulte segurança de confiança parcial do WPF.

O WebBrowser controle dá suporte à hospedagem de documentos HTML, navegação e interoperabilidade de script/código gerenciado. Para obter informações detalhadas sobre o WebBrowser controle, consulte WebBrowser.

Assim como Frame, navegar até HTML usando WebBrowser requer permissões especiais. Por exemplo, de um aplicativo com confiança parcial, você só pode navegar para o HTML que está localizado no site de origem. Para obter mais informações, consulte segurança de confiança parcial do WPF.

Se você tiver dados armazenados como objetos personalizados, uma maneira de exibir esses dados é criar um Page conteúdo associado a esses objetos (consulte a Visão geral da associação de dados). Se você não precisar da sobrecarga de criar uma página inteira apenas para exibir os objetos, poderá navegar diretamente até eles.

Considere a Person classe que é implementada no código a seguir.

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

Para navegar até ele, você chama o NavigationWindow.Navigate método, conforme demonstrado pelo código a seguir.

<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

A figura a seguir mostra o resultado.

Uma página que navega até uma classe

Nessa figura, você pode ver que nada de útil é exibido. Na verdade, o valor exibido é o valor retornado do ToString método para o objeto Person ; por padrão, esse é o único valor que o WPF pode usar para representar seu objeto. Você pode substituir o ToString método para retornar informações mais significativas, embora ainda seja apenas um valor de cadeia de caracteres. Uma técnica que você pode usar que aproveita os recursos de apresentação do WPF é usar um modelo de dados. Você pode implementar um modelo de dados que o WPF pode associar a um objeto de um tipo específico. O código a seguir mostra um modelo de dados para o Person objeto.

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

Aqui, o modelo de dados é associado ao Person tipo usando a x:Type extensão de marcação no DataType atributo. Em seguida, o modelo de dados associa elementos TextBlock (veja TextBlock) às propriedades da Person classe. A figura a seguir mostra a aparência atualizada do Person objeto.

Navegando até uma classe que tem um modelo de dados

Uma vantagem dessa técnica é a consistência que você obtém ao ser capaz de reutilizar o modelo de dados para exibir seus objetos consistentemente em qualquer lugar em seu aplicativo.

Para obter mais informações sobre modelos de dados, consulte Visão geral da Modelagem de Dados.

Segurança

O suporte à navegação do WPF permite que os XBAPs sejam navegados pela Internet e permite que os aplicativos hospedem conteúdo de terceiros. Para proteger aplicativos e usuários contra comportamentos prejudiciais, o WPF fornece uma variedade de recursos de segurança que são discutidos em Segurança e segurança de confiança parcial do WPF.

Consulte também