Partilhar via


Visão geral da navegação

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

Page, Hyperlink, NavigationServicee o diário formam o núcleo do suporte de navegação oferecido pelo WPF. Esta visão geral explora esses recursos em detalhes antes de abordar o suporte avançado à navegação que inclui navegação para arquivos soltos XAML, arquivos HTML e objetos.

Observação

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

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 Visão geral de aplicativos de navegador WPF XAML.

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

Implementando uma página

No WPF, você pode navegar para 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 melhorar sua aparência e simplificar o desenvolvimento.

Usando Page, você pode implementar declarativamente uma página navegável de conteúdo XAML usando marcações como as seguintes.

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

Um Page implementado na marcação XAML tem Page como seu elemento raiz e requer a declaração de namespace WPF XML. O elemento Page contém o conteúdo para o qual você deseja navegar e exibir. Você adiciona conteúdo definindo o elemento de propriedade Page.Content, 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 elemento Page são considerados o conteúdo de um Page e, consequentemente, você não precisa usar a declaração Page.Content explícita. A marcação a seguir é o equivalente declarativo à amostra 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 elemento Page. Para obter mais informações, consulte WPF Content Model.

Um Page somente de marcação é útil para mostrar conteúdo. No entanto, um Page também pode exibir controles que permitem que os usuários interajam com a página e pode responder à interação do usuário manipulando eventos e chamando a lógica do aplicativo. Um Page interativo é 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 trabalhem juntos, a seguinte configuração é necessária:

  • Na marcação, o elemento Page deve incluir o atributo x:Class. Quando o aplicativo é criado, a existência de x:Class no arquivo de marcação faz com que o mecanismo de compilação 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 partial gerada implementa InitializeComponent, que é chamada para registrar os eventos e definir as propriedades que são implementadas na marcação.

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

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

Observação

Quando você adiciona um novo Page ao seu projeto usando o Visual Studio, o Page é implementado usando marcação e 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ê pode navegar até ele. Para especificar o primeiro Page para o qual uma aplicação navega, é necessário configurar o Pageinicial.

Configurando uma página inicial

Os XBAPs exigem uma certa quantidade de infraestrutura de aplicativos para serem hospedados em um navegador. No WPF, a classe Application faz parte de uma definição de aplicativo que estabelece a infraestrutura de aplicativo necessária (consulte Visão geral do gerenciamento de aplicativos).

Uma definição de aplicação geralmente é implementada usando marcação e código subjacente, com o arquivo de marcação configurado como um itemApplicationDefinition do MSBuild. A seguir está 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 a sua definição de aplicativo para especificar um início Page, o qual é o Page que é automaticamente carregado quando o XBAP é iniciado. Para fazer isso, defina a propriedade StartupUri com o identificador de recurso uniforme (URI) para o Pagedesejado.

Observação

Na maioria das vezes, o Page é compilado ou implementado com um aplicativo. Nesses casos, o URI que identifica um Page é um URI de um pacote, em conformidade com o esquema do pacote . URIs de pacote são discutidos mais detalhadamente no capítulo URIs de pacote no WPF. Você também pode navegar para 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 atributo StartupUri é definido com um URI de pacote relativo que identifica HomePage.xaml. Quando o XBAP é iniciado, HomePage.xaml é automaticamente aberto e exibido. 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 Visão geral de aplicativos de navegador WPF XAML e Implantando um aplicativo WPF.

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

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

WindowTitle, WindowWidthe WindowHeight podem ser definidos 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, altura, largura

Um XBAP típico compreende várias páginas. A maneira mais simples de navegar de uma página para outra é usar um Hyperlink. Você pode adicionar declarativamente um Hyperlink a um Page usando o elemento Hyperlink, 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 elemento Hyperlink requer o seguinte:

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

  • Conteúdo no qual um usuário pode clicar para iniciar a navegação, como texto e imagens (para o conteúdo que o elemento Hyperlink 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 no Hyperlink faz com que o XBAP navegue até o Page identificado pelo atributo NavigateUri. Além disso, o XBAP adiciona uma entrada para o Page anterior à lista de páginas recentes no Internet Explorer. Isso é mostrado na figura a seguir.

botões Voltar e Avançar

Além de suportar a navegação de uma Page para outra, Hyperlink também suporta navegação por fragmentos.

Navegação de fragmentos

A navegação de fragmentos de é a navegação para um fragmento de conteúdo no atual Page ou noutro Page. No WPF, um fragmento de conteúdo é o conteúdo contido por um elemento nomeado. Um elemento nomeado é um elemento que tem seu atributo Name definido. A marcação a seguir mostra um elemento TextBlock nomeado 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 navegue até um fragmento de conteúdo, o atributo NavigateUri deve incluir o seguinte:

  • O URI do Page com o fragmento de 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

A seguir mostra um exemplo de um Hyperlink 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 de fragmentos que, em parte, requer a manipulação do evento NavigationService.FragmentNavigation.

Importante

Você pode aceder a fragmentos em páginas XAML soltas (arquivos XAML exclusivamente de marcação com Page como elemento raiz) somente se as páginas puderem ser acessadas via HTTP.

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

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

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

Observação

É possível que um aplicativo WPF tenha mais de um NavigationServiceativo no momento. Para obter mais informações, consulte Anfitriões de Navegação mais à frente 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 nome. Isso significa que, desde que o progenitor direto ou indireto de um Hyperlink seja um anfitrião de navegação (consulte Navigation Hosts), Hyperlink poderá encontrar e usar o serviço de navegação do anfitrião para processar um pedido de navegação.

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

  • Quando você precisa instanciar um Page usando um construtor sem parâmetros.

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

  • Quando o Page ao qual é necessário navegar 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 método Navigate do objeto NavigationService. Para tal, é necessário obter uma referência a um NavigationService.

Obtendo uma referência ao NavigationService

Por motivos abordados na seção Hosts de Navegação, uma aplicação WPF pode ter mais de um NavigationService. Isso significa que o seu código precisa de uma maneira de encontrar um NavigationService, que geralmente é o NavigationService que navegou para o Pageatual. Você pode obter uma referência a um NavigationService chamando o método staticNavigationService.GetNavigationService. Para obter o NavigationService que navegou para um determinado Page, passas uma referência ao Page como argumento do método GetNavigationService. O código a seguir mostra como obter o NavigationService para o Pageatual.

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 encontrar o NavigationService de um Page, o 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

Um Page só pode obter uma referência ao seu 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 sem parâmetros. O Page com o construtor non-parameterless é mostrado na marcação e 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 para o Page com o construtor 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 non-parameterless e chamando o método NavigationService.Navigate. Navigate aceita uma referência ao objeto para o qual o 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 você só pode determinar o URI do pacote em tempo de execução, por exemplo), você pode usar o método NavigationService.Navigate. 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 tiver o mesmo URI do pacote que o URI do pacote armazenado na propriedade NavigationService.Source. Para forçar o WPF a baixar a página atual novamente, você pode chamar o método NavigationService.Refresh, 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 rastrear 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 sobre o progresso da 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 ao navegar para o conteúdo solicitado.

  • LoadCompleted. Ocorre quando o conteúdo para o qual foi navegado é carregado e analisado e começou a renderização.

  • 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 de o conteúdo de origem ter sido carregado, caso o fragmento desejado esteja em outro conteúdo.

Os eventos de navegação são gerados na ordem ilustrada pela figura a seguir.

Fluxograma de navegação de página

Em geral, um Page não está preocupado com esses eventos. É mais provável que uma aplicação esteja preocupada com eles e, por essa razão, esses eventos também são sinalizados pela classe Application:

Toda vez que NavigationService gera um evento, a classe Application gera o evento correspondente. Frame e NavigationWindow oferecem os mesmos eventos para detetar a navegação dentro de seus respetivos escopos.

Em alguns casos, um(a) Page pode estar interessada(o) nesses eventos. Por exemplo, um Page pode manipular o evento NavigationService.Navigating para determinar se deve 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 registares um manipulador com um evento de navegação de um Page, como faz o exemplo anterior, também deverás cancelar o registo do manipulador de eventos. Se não o fizeres, podem haver consequências em relação a como a navegação do WPF lembra-se da navegação Page usando o jornal.

Lembrando a navegação com o diário

O WPF utiliza duas pilhas para memorizar as páginas das quais navegou: uma pilha de retroceder e uma pilha de avançar. Quando se navega do atual para um novo ou avança para um existente, o atual é adicionado à pilha de retorno. Quando se navega da atual de volta para a anterior, a atual é adicionada à pilha de avançodo . A pilha de trás, a pilha de encaminhamento e a funcionalidade para gerenciá-los são coletivamente chamados de diário. Cada item na pilha de retorno e na pilha de avanço é uma instância da classe e é referido como uma entrada de diário.

Conceitualmente, o diário funciona da mesma forma que os botões Voltar e Avançar no Internet Explorer. Estes são mostrados na figura a seguir.

botões Voltar e Avançar

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

Importante

No Internet Explorer, quando um utilizador navega para longe e de volta para um XBAP, apenas as entradas de diário para páginas que não se mantiveram ativas são retidas no diário. Para discussão sobre como manter as páginas vivas, consulte Page Lifetime e o Journal mais adiante neste tópico.

Por predefinição, o texto correspondente a 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 JournalEntry.Name anexado.

  2. O valor do atributo Page.Title.

  3. O valor do atributo Page.WindowTitle e o URI associado ao Pageatual.

  4. A URI do Pageatual. (Padrão)

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

O exemplo a seguir usa o atributo Page.Title 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 no diário usando o Voltar , Avançare Páginas Recentes no Internet Explorer, você também pode navegar no diário usando mecanismos declarativos e programáticos fornecidos pelo WPF. Um motivo para fazer isso é fornecer interfaces de usuário de navegação personalizadas em suas páginas.

Você pode adicionar declarativamente o suporte à navegação no diário usando os comandos de navegação expostos pelo NavigationCommands. O exemplo a seguir demonstra como usar o comando BrowseBack navigation.

<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 no diário usando um dos seguintes membros da classe NavigationService:

O registo também pode ser manipulado programaticamente, como discutido em Manutenção do Estado do Conteúdo com Histórico de Navegação mais adiante 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 rico, incluindo gráficos, animações e mídia. A pegada de memória para páginas como essas pode ser bastante grande, especialmente se mídias de vídeo e áudio forem usadas. Dado que o registro "lembra" as páginas que foram visitadas, tal XBAP poderia rapidamente consumir uma grande e notável quantidade de memória.

Por esse motivo, o comportamento padrão do diário é armazenar metadados de Page em cada entrada de diário, em vez de uma referência a um objeto Page. Quando se navega para uma entrada de diário, os seus metadados Page são usados para criar uma nova instância do Pageespecificado. Como consequência, cada Page que é navegável tem o tempo de vida ilustrado pela seguinte figura.

Tempo de vida da página

Embora o uso do comportamento padrão de registro no diário possa economizar no consumo de memória, o desempenho de renderização por página pode ser reduzido; Reinstanciar um Page pode exigir muito tempo, especialmente se ele tiver muito conteúdo. Se você precisar manter uma instância Page no diário, você pode recorrer a duas técnicas para fazê-lo. Primeiro, você pode navegar programaticamente para um objeto Page chamando o método NavigationService.Navigate.

Em segundo lugar, pode definir que o WPF mantenha uma instância de um Page no diário, definindo a propriedade KeepAlive como true (por padrão, é false). Como 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>

O tempo de vida de um Page que é mantido vivo é sutilmente diferente de um que não é. A primeira vez que se navega até um Page que é preservado, ele é instanciado como um Page que não é preservado. No entanto, como uma instância do Page é mantida no diário, esta não é instanciada novamente enquanto permanecer no diário. Consequentemente, se um Page tiver lógica de inicialização que precise ser chamada toda vez que se navegue para o Page, deverá movê-la do construtor para um manipulador do evento Loaded. Como mostrada na figura a seguir, os eventos Loaded e Unloaded ainda são gerados cada vez que se navega para e a partir de um Page, respectivamente.

Quando os eventos Loaded e Unloaded são gerados

Quando um Page não é mantido vivo, não deves fazer o seguinte:

  • Armazene uma referência a ele ou a qualquer parte dele.

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

Fazer qualquer um deles criará referências que forçam o Page a ser retido na memória, mesmo depois de ter sido removido da revista.

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

Mantendo o estado do conteúdo com o histórico de navegação

Se um Page não é mantido vivo e tem controles que coletam dados do usuário, o que acontece com os dados se um usuário navega para longe e de volta 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 do Page é criada a cada navegação, os controles que coletaram os dados são reinstanciados e os dados são perdidos.

Felizmente, o diário fornece suporte para lembrar dados em Page navegações, incluindo dados de controle. Especificamente, o registo de diário para cada Page atua como um contêiner temporário para o estado associado a Page. Os passos seguintes descrevem como este suporte é usado quando se navega para um Page:

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

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

  3. O novo Page é acedido.

Quando se navega de volta para a página Page usando o jornal, ocorrem os seguintes passos:

  1. O Page (a entrada de diário superior na pilha traseira) é instanciado.

  2. O Page é atualizado com o estado armazenado no registo de diário para o Page.

  3. O Page é navegado de volta para.

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

Se um Page usa esses controlos, os dados inseridos neles são mantidos durante as navegações de Page, como demonstrado pela Cor FavoritaListBox na figura a seguir.

Página com controles que lembram o estado

Quando um Page tem controlos diferentes dos da lista anterior, ou quando o estado é armazenado em objetos personalizados, é necessário escrever código para fazer com que o diário mantenha o estado nas navegações de Page.

Se você precisar se lembrar de pequenos pedaços de estado em Page navegações, poderá usar propriedades de dependência (consulte DependencyProperty) configuradas com o sinalizador de metadados FrameworkPropertyMetadata.Journal.

Se o estado que o Page precisa lembrar nas navegações compreende múltiplas partes de dados, pode achar menos trabalhoso em termos de código encapsular o estado numa única classe e implementar a interface IProvideCustomContentState.

Se você precisa navegar por vários estados de um único Page, sem navegar a partir do Page em si, 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 da Web usam; Cookies são partes arbitrárias de dados que são armazenados por um aplicativo em uma máquina cliente durante ou entre sessões de aplicativos. Os dados de cookies normalmente assumem a forma de um par nome/valor no seguinte formato.

Nome=Valor

Quando os dados são passados para SetCookie, juntamente com a Uri do 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. Este tipo de cookie é referido como um cookie de sessão .

Para armazenar um cookie nas sessões do aplicativo, uma data de expiração deve ser adicionada ao cookie, usando o seguinte formato.

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

Um cookie com uma data de expiração é armazenado na pasta Temporary Internet Files da instalação atual do Windows até que o cookie expire. Esse cookie é conhecido como um cookie persistente porque persiste nas sessões do aplicativo.

Você recupera cookies de sessão e persistentes chamando o método GetCookie, passando a Uri do local onde o cookie foi definido com o método SetCookie.

A seguir estão algumas das maneiras pelas quais os cookies são suportados no WPF:

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

  • Os cookies criados por um XBAP podem ser acedidos a partir do navegador.

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

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

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

  • Tanto XBAPs de nível superior quanto XBAPs hospedados em IFRAMES podem acessar cookies.

  • O suporte a cookies no WPF é o mesmo para todos os navegadores suportados.

  • No Internet Explorer, a política P3P referente aos cookies é cumprida pelo WPF, especialmente em relação a XBAPs próprios 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 sem parâmetros do Page. Note que se você usar esta técnica, você deve manter o Page vivo; caso contrário, da próxima vez que você navegar para o Page, o WPF reinstanciará o Page usando o construtor sem parâmetros.

Como alternativa, o seu Page pode implementar propriedades que são definidas com os dados a transmitir. As coisas se tornam complicadas, no entanto, quando um Page precisa passar dados de volta para o Page que navegou até ele. O problema é que a navegação não suporta nativamente mecanismos para garantir que se regressará a um Page após a navegação. Essencialmente, a navegação não suporta semântica de chamada/retorno. Para resolver esse problema, o WPF fornece a classe PageFunction<T> 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é este ponto, você viu a gama de serviços de navegação que você provavelmente usará para criar aplicativos com conteúdo navegável. Estes serviços foram discutidos no contexto dos XBAPs, embora não se limitem aos XBAPs. Sistemas operacionais modernos e aplicativos do Windows aproveitam a experiência do navegador dos usuários modernos para incorporar navegação no estilo do navegador em aplicativos autônomos. Exemplos comuns incluem:

  • Word Thesaurus: Navegue pelas opções de palavras.

  • Explorador de Ficheiros: Navegue por ficheiros e pastas.

  • Wizards: 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 do navegador em seus aplicativos autônomos, você pode usar a classe NavigationWindow. NavigationWindow deriva do Window e o estende com o mesmo suporte para navegação que os XBAPs fornecem. Você pode usáNavigationWindow como a janela principal do seu aplicativo autônomo ou como uma janela secundária, como uma caixa de diálogo.

Para implementar um NavigationWindow, como acontece com a maioria das classes de nível superior no WPF (Window, Pagee assim por diante), usa-se uma combinação de marcação e código associado. 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 o NavigationWindow é aberto. Se o NavigationWindow for a janela principal do aplicativo, você poderá usar o atributo StartupUri 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 o NavigationWindow como a janela principal de um aplicativo autônomo.

Uma janela principal

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

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

A definição das 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. Caso não faça nenhum dos dois, pode utilizar um atalho. Se você especificar o URI do pacote de um Page como o 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 desejar que uma janela secundária do aplicativo, como uma caixa de diálogo, seja um NavigationWindow, você pode usar o código no exemplo a seguir para abri-la.

// 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 pode ver, NavigationWindow exibe botões Voltar e Avançar , ao estilo do Internet Explorer, que permitem aos utilizadores navegar pelo jornal. 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 janela de navegação

Se as suas páginas fornecerem o seu próprio suporte de navegação de jornal e interface do utilizador, pode ocultar os botões Voltar e Avançar exibidos por NavigationWindow ao definir o valor da propriedade ShowsNavigationUI para false.

Como alternativa, você pode usar o suporte à personalização no WPF para substituir a interface do usuário do próprio NavigationWindow.

A classe Frame

Tanto o navegador quanto o 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 deve ser hospedado dentro de outro conteúdo. Você pode inserir conteúdo navegável em outro conteúdo usando a classe Frame. Frame fornece o mesmo suporte que NavigationWindow e XBAPs.

O exemplo a seguir mostra como adicionar um Frame a um Page declarativamente usando o elemento 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>

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

Um quadro que navegou entre várias páginas

Não é necessário limitar-se a usar Frame 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 periódico. Se um Frame fizer parte do conteúdo hospedado dentro de um NavigationWindow ou XBAP, Frame usará o diário que pertence ao NavigationWindow ou XBAP. Às vezes, porém, um Frame pode precisar ser responsável por seu próprio diário. Uma razão para fazer isso é permitir a navegação no diário dentro das páginas hospedadas por um Frame. Isto é ilustrado pela figura seguinte.

Diagrama de Quadro e Página

Nesse caso, você pode configurar o Frame para usar seu próprio diário definindo a propriedade JournalOwnership do Frame como 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 seguinte ilustra o efeito de navegar dentro de um Frame que usa o 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 um Frame fizer parte do conteúdo hospedado em um Window, Frame usará seu próprio diário e, consequentemente, exibirá sua própria interface do usuário de navegação.

Se a experiência do usuário exigir que um Frame forneça seu próprio diário sem mostrar a interface do usuário de navegação, você poderá ocultar a interface do usuário de navegação definindo o 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 anfitriões de navegação. Um host de navegação é uma classe capaz de navegar e exibir conteúdo. Para fazer isto, cada host de navegação usa o seu próprio NavigationService e registro. A construção básica de um host de navegação é mostrada na figura a seguir.

diagramas do Navigator

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

Além de usar NavigationService e um diário, os hosts de navegação implementam os mesmos membros que NavigationService implementa. Isto é ilustrado pela figura seguinte.

um diário numa moldura e numa 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 um Frame hospedado 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 diário na pilha de retrocesso e na pilha de avanço, respectivamente.

Como mencionado anteriormente, mais de um periódico pode existir dentro de um aplicativo. A figura a seguir fornece um exemplo de quando isso pode acontecer.

Vários periódicos dentro de um aplicativo

Ao longo deste tópico, o Page e os pacotes XBAP foram usados para demonstrar as várias capacidades de navegação do WPF. No entanto, um Page compilado para um aplicativo não é o único tipo de conteúdo para o qual se pode navegar, e os XBAPs de pacote não são a única forma de identificar conteúdo.

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

Um arquivo XAML solto é 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 seguinte conteúdo 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 abre e navega e exibe o conteúdo. Isso é mostrado na figura a seguir.

Exibição do conteúdo no arquivo Person.XAML

Você pode exibir um arquivo XAML solto do seguinte:

  • Um site na máquina local, na intranet ou na Internet.

  • Uma partilha de ficheiros UNC (Convenção Universal de Nomenclatura).

  • O disco local.

Um arquivo XAML solto pode ser adicionado aos favoritos do navegador ou ser a página inicial 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 solto é que você só pode hospedar conteúdo que seja seguro para execução 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 WPF Partial Trust Security.

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

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

Navegar para HTML requer permissões especiais. Por exemplo, não é possível navegar a partir 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 WPF Partial Trust Security.

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

Como Frame, navegar para HTML usando WebBrowser requer permissões especiais. Por exemplo, a partir de um aplicativo de confiança parcial, você pode navegar apenas para HTML localizado no site de origem. Para obter mais informações, consulte WPF Partial Trust Security.

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

Considere a classe Person 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 método NavigationWindow.Navigate, 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 para uma classe

A partir desta figura, você pode ver que nada de útil é exibido. Na verdade, o valor exibido é o valor de retorno do método ToString para o objeto Person; por padrão, esse é o único valor que o WPF pode usar para representar seu objeto. Você pode substituir o método ToString 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 objeto 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>

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

Navegando para uma classe que tem um modelo de dados

Uma vantagem dessa técnica é a consistência que você ganha 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 de Modelos de Dados.

Segurança

O suporte à navegação do WPF permite que XBAPs sejam utilizados para navegação na Internet e permite aos aplicativos hospedar 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 Security e WPF Partial Trust Security.

Ver também