Compartir a través de


Información general de navegación

Windows Presentation Foundation (WPF) admite la navegación de estilo explorador que se puede usar en dos tipos de aplicaciones: aplicaciones independientes y aplicaciones de explorador XAML (XBAP). Para empaquetar el contenido de la navegación, WPF proporciona la Page clase . Puede navegar de uno Page a otro de manera declarativa, mediante un Hyperlink, o de manera programática, mediante el NavigationService. WPF usa el diario para recordar las páginas desde las que se ha navegado y para volver a ellas.

Page, Hyperlink, NavigationService, y el diario forman el núcleo del soporte de navegación que ofrece WPF. En esta introducción se exploran detalladamente estas características antes de cubrir la compatibilidad con la navegación avanzada que incluye la navegación a archivos flexible del lenguaje de marcado de aplicaciones extensibles (XAML), archivos HTML y objetos.

Nota:

En este tema, el término "explorador" hace referencia solo a los exploradores que pueden hospedar aplicaciones WPF, que actualmente incluye Microsoft Internet Explorer y Firefox. Cuando las características específicas de WPF solo son compatibles con un explorador determinado, se hace referencia a la versión del explorador.

En este tema se proporciona información general sobre las funcionalidades de navegación clave en WPF. Estas funcionalidades están disponibles para aplicaciones independientes y XBAP, aunque este tema los presenta en el contexto de un XBAP.

Nota:

En este tema no se describe cómo compilar e implementar XBAP. Para obtener más información sobre XBAP, consulta Introducción a las aplicaciones de explorador XAML de WPF.

En esta sección se explican y se muestran los siguientes aspectos de la navegación:

Implementación de una página

En WPF, puede ir a varios tipos de contenido que incluyen objetos de .NET Framework, objetos personalizados, valores de enumeración, controles de usuario, archivos XAML y archivos HTML. Sin embargo, encontrará que la forma más común y cómoda de empaquetar contenido es mediante Page. Además, Page implementa características específicas de navegación para mejorar su apariencia y simplificar el desarrollo.

Con Page, puedes implementar mediante declaración una página navegable de contenido XAML mediante marcado como el siguiente.

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

Un Page implementado en el marcado XAML tiene Page como elemento raíz y requiere la declaración del espacio de nombres XML de WPF. El Page elemento contiene el contenido al que desea navegar y mostrar. Para agregar contenido, establezca el elemento de propiedad Page.Content, como se muestra en el marcado siguiente.

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

Page.Content solo puede contener un elemento secundario; en el ejemplo anterior, el contenido es una sola cadena, "Hello, Page!" En la práctica, normalmente usará un control de diseño como elemento secundario (vea Diseño) para contener y componer el contenido.

Los elementos secundarios de un Page elemento se consideran el contenido de Page y, por lo tanto, no es necesario usar la declaración explícita Page.Content . El marcado siguiente es el equivalente declarativo al ejemplo anterior.

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

En este caso, Page.Content se establece automáticamente con los elementos secundarios del Page elemento . Para obtener más información, vea Modelo de contenido de WPF.

Un Page de solo marcado es útil para mostrar contenido. Sin embargo, un Page también puede mostrar controles que permiten a los usuarios interactuar con la página, y puede responder a la interacción del usuario controlando eventos y llamando a la lógica de la aplicación. Un interactivo Page se implementa mediante una combinación de marcado y código subyacente, como se muestra en el ejemplo siguiente.

<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 un archivo de marcado y un archivo de código subyacente funcionen juntos, se requiere la siguiente configuración:

  • En el marcado, el elemento Page debe incluir el atributo x:Class. Cuando se compila la aplicación, la existencia de x:Class en el archivo de marcado hace que el motor de compilación de Microsoft (MSBuild) cree una clase partial que derive de Page y tenga el nombre especificado por el atributo x:Class. Esto requiere la adición de una declaración de espacio de nombres XML para el esquema XAML ( xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ). La clase generada partial implementa InitializeComponent, que se invoca para registrar los eventos y establecer las propiedades implementadas en el marcado.

  • En el código subyacente, la clase debe ser de tipo partial con el mismo nombre que especifica el atributo x:Class en el marcado, y debe derivar de Page. Esto permite asociar el archivo de código subyacente a la partial clase que se genera para el archivo de marcado cuando se compila la aplicación (vea Building a WPF Application).

  • En el código subyacente, la Page clase debe implementar un constructor que llame al InitializeComponent método . InitializeComponent se implementa mediante la clase generada partial del archivo de marcado para registrar eventos y establecer propiedades definidas en el marcado.

Nota:

Al agregar un nuevo Page elemento al proyecto mediante Visual Studio, Page se implementa con marcado y código subyacente, e incluye la configuración necesaria para crear la asociación entre los archivos de marcado y código subyacente, tal como se describe aquí.

Una vez que tenga un Page, puede navegar a él. Para especificar la primera Page a la que navega una aplicación, debe configurar el inicio Page.

Configuración de una página de inicio

Los XBAP requieren que se hospede una determinada cantidad de infraestructura de aplicaciones en un explorador. En WPF, la Application clase forma parte de una definición de aplicación que establece la infraestructura de aplicaciones necesaria (consulte Introducción a la administración de aplicaciones).

Normalmente, una definición de aplicación se implementa mediante marcado y código subyacente, con el archivo de marcado configurado como un elemento de MSBuildApplicationDefinition . A continuación se muestra una definición de aplicación para un 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

Un XBAP puede usar su definición de aplicación para especificar un inicio Page, que es el Page que se carga automáticamente cuando se inicia el XBAP. Para ello, configure la propiedad StartupUri con el identificador uniforme de recursos (URI) para el elemento deseado Page.

Nota:

En la mayoría de los casos, Page se compila en o se implementa con una aplicación. En estos casos, el URI que identifica un Page es un URI de paquete, que es un URI que se ajusta al esquema de paquete . Los URI de paquete se describen más adelante en URI de paquete en WPF. También puede navegar al contenido mediante el esquema http, que se describe a continuación.

Puede establecer StartupUri de manera declarativa en el marcado, como se muestra en el ejemplo siguiente.

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

En este ejemplo, el StartupUri atributo se establece con un URI de paquete relativo que identifica HomePage.xaml. Cuando se inicia XBAP, se navega automáticamente a HomePage.xaml y se muestra. Esto se muestra en la ilustración siguiente, que muestra un XBAP que se inició desde un servidor web.

Página XBAP

Nota:

Para obtener más información sobre el desarrollo y la implementación de XBAP, consulta Introducción a las aplicaciones de explorador XAML de WPF e Implementación de una aplicación WPF.

Configuración del título, el ancho y el alto de la ventana host

Una cosa que puede haber observado en la ilustración anterior es que el título del explorador y el panel de pestañas es el URI del XBAP. Además de ser largo, el título no es atractivo ni informativo. Por este motivo, Page ofrece una manera de cambiar el título estableciendo la WindowTitle propiedad . Además, puede configurar el ancho y el alto de la ventana del explorador estableciendo WindowWidth y WindowHeight, respectivamente.

WindowTitle, WindowWidthy WindowHeight se pueden establecer mediante declaración en el marcado, como se muestra en el ejemplo siguiente.

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

El resultado se muestra en la ilustración siguiente.

Título de la ventana, alto, ancho

Un XBAP típico consta de varias páginas. La manera más sencilla de navegar de una página a otra es usar un Hyperlink. Puede agregar de manera declarativa un elemento Hyperlink a Page utilizando el elemento Hyperlink, que se muestra en el marcado de ejemplo siguiente.

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

Un Hyperlink elemento requiere lo siguiente:

  • Identificador URI del paquete al que Page navegar, tal y como el atributo NavigateUri especifica.

  • Contenido que un usuario puede hacer clic para iniciar la navegación, como texto e imágenes (para el contenido que el Hyperlink elemento puede contener, vea Hyperlink).

En la ilustración siguiente se muestra un XBAP que tiene un Page con un Hyperlink.

Página con hipervínculo

Como cabría esperar, al hacer clic en Hyperlink, el XBAP navega al Page, el cual está identificado por el atributo NavigateUri. Además, el XBAP agrega una entrada para el anterior Page a la lista Páginas recientes en Internet Explorer. Esto se muestra en la siguiente ilustración.

Botones Atrás y Adelante

Además de admitir la navegación de un Page a otro, Hyperlink también admite la navegación por fragmentos.

Navegación por fragmentos

La navegación por fragmentos es la navegación a un fragmento de contenido en el objeto actual Page u otro Page. En WPF, un fragmento de contenido es el contenido que contiene un elemento con nombre. Un elemento con nombre es un elemento que tiene su Name conjunto de atributos. El marcado siguiente muestra un elemento con nombre TextBlock que contiene un fragmento de contenido.

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

Hyperlink Para que vaya a un fragmento de contenido, el NavigateUri atributo debe incluir lo siguiente:

  • El URI de Page con el fragmento de contenido para navegar.

  • Carácter "#".

  • Nombre del elemento en que Page contiene el fragmento de contenido.

Un URI de fragmento tiene el formato siguiente.

PageURI#ElementName

A continuación se muestra un ejemplo de un Hyperlink que está configurado para navegar a un fragmento de contenido.

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

Nota:

En esta sección se describe la implementación de navegación por fragmentos predeterminada en WPF. WPF también le permite implementar su propio esquema de navegación de fragmentos que, en parte, requiere controlar el NavigationService.FragmentNavigation evento.

Importante

Puedes navegar a fragmentos en páginas XAML sueltas (archivos XAML de solo marcado con Page como elemento raíz) solo si las páginas se pueden examinar a través de HTTP.

Sin embargo, una página XAML flexible puede navegar a sus propios fragmentos.

Aunque Hyperlink permite a un usuario iniciar la navegación a un determinado Page, la clase realiza NavigationService el trabajo de localizar y descargar la página. Básicamente, NavigationService proporciona la capacidad de procesar una solicitud de navegación en nombre del código de cliente, como Hyperlink. Además, NavigationService implementa soporte avanzado para realizar el seguimiento e influir en una solicitud de navegación.

Cuando se hace clic en Hyperlink, WPF llama a NavigationService.Navigate para localizar y descargar el recurso ubicado en el URI de paquete especificado Page. El descargado Page se convierte en un árbol de objetos cuyo objeto raíz es una instancia del descargado Page. Una referencia al objeto raíz Page se almacena en la NavigationService.Content propiedad . El URI del paquete para el contenido al que se ha navegado se almacena en la NavigationService.Source propiedad , mientras que almacena NavigationService.CurrentSource el URI del paquete para la última página a la que se ha navegado.

Nota:

Es posible que una aplicación WPF tenga más de una activa actualmente NavigationService. Para obtener más información, vea Hosts de navegación más adelante en este tema.

Navegación mediante programación con el servicio de navegación

No necesitas saber sobre NavigationService si la navegación se implementa de manera declarativa en el marcado usando Hyperlink, porque Hyperlink usa el NavigationService en tu nombre. Esto significa que, siempre que el elemento primario directo o indirecto de un Hyperlink sea un anfitrión de navegación (consulte Anfitriones de Navegación), Hyperlink podrá encontrar y usar el servicio de navegación del anfitrión de navegación para procesar una solicitud de navegación.

Sin embargo, hay situaciones en las que es necesario usar NavigationService directamente, incluidas las siguientes:

  • Cuando necesite crear una instancia Page de mediante un constructor sin parámetros.

  • Cuando necesite establecer las propiedades en Page antes de navegar al recurso.

  • Cuando solo se puede determinar en tiempo de ejecución a qué Page se debe navegar.

En estas situaciones, debe escribir código para iniciar la navegación programáticamente, llamando al método Navigate del objeto NavigationService. Esto requiere obtener una referencia a NavigationService.

Obtener una referencia a NavigationService

Por motivos que se tratan en la sección Hosts de navegación, una aplicación WPF puede tener más de uno NavigationService. Esto significa que el código necesita una manera de encontrar un NavigationService, que suele ser el NavigationService que ha navegado hasta el Page actual. Puede obtener una referencia a un NavigationService mediante una llamada al staticNavigationService.GetNavigationService método . Para obtener el NavigationService que ha navegado a un determinado Page, se pasa una referencia de Page como argumento del método GetNavigationService. En el siguiente código se muestra cómo obtener el NavigationService para el Page actual.

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 un atajo para encontrar el NavigationService de un Page, Page implementa la propiedad NavigationService. Esto se muestra en el ejemplo siguiente.

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

Nota:

Un Page objeto solo puede obtener una referencia a su NavigationService cuando Page genera el Loaded evento.

Navegación programática a un objeto de página

En el ejemplo siguiente se muestra cómo usar NavigationService para navegar mediante programación a .Page La navegación programática es necesaria porque el Page al que se navega solo se puede instanciar mediante un único constructor que no es sin parámetros. Con Page el constructor sin parámetros se muestra en el siguiente marcado y código.

<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

Que Page navega hasta Page con el constructor sin parámetros se muestra en el siguiente marcado y código.

<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

Cuando se hace clic en Hyperlink de este Page, se inicia la navegación instanciando el Page al que se debe navegar utilizando el constructor con parámetros y llamando al método NavigationService.Navigate. Navigate acepta una referencia al objeto al que NavigationService navegará, en lugar de a un URI de paquete.

Navegación mediante programación con un URI de paquete

Si necesita construir un URI de paquete mediante programación (cuando solo puede determinar el URI del paquete en tiempo de ejecución, por ejemplo), puede usar el NavigationService.Navigate método . Esto se muestra en el ejemplo siguiente.

<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

Actualizar la página actual

No se descarga Page si tiene el mismo URI de paquete que el URI del paquete que se almacena en la propiedad NavigationService.Source. Para forzar que WPF descargue de nuevo la página actual, puede llamar al NavigationService.Refresh método , como se muestra en el ejemplo siguiente.

<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

Hay muchas maneras de iniciar la navegación, como ha visto. Cuando se inicia la navegación y mientras la navegación está en curso, puede realizar un seguimiento e influir en la navegación mediante los siguientes eventos implementados por NavigationService:

  • Navigating. Se produce cuando se solicita una nueva navegación. Se puede usar para cancelar la navegación.

  • NavigationProgress. Se produce periódicamente durante una descarga para proporcionar información de progreso de navegación.

  • Navigated. Se produce cuando la página se ha localizado y descargado.

  • NavigationStopped. Se produce cuando se detiene la navegación (llamando a StopLoading), o cuando se solicita una nueva navegación mientras se está realizando una navegación actual.

  • NavigationFailed. Ocurre cuando se produce un error al navegar al contenido solicitado.

  • LoadCompleted. Se produce cuando se carga y analiza el contenido al que se ha navegado y se ha iniciado la representación.

  • FragmentNavigation. Tiene lugar cuando empieza la navegación hacia un fragmento de contenido, lo cual ocurre:

    • Inmediatamente, si el fragmento deseado está en el contenido actual.

    • Una vez cargado el contenido de origen, si el fragmento deseado está en otro contenido.

Los eventos de navegación se generan en el orden que se muestra en la siguiente figura.

Gráfico de flujo de navegación de página

En general, Page no se preocupa por estos eventos. Es más probable que una aplicación se preocupe por ellos y, por ese motivo, estos eventos también se generan mediante la Application clase :

Cada vez NavigationService que genera un evento, la Application clase genera el evento correspondiente. Frame y NavigationWindow ofrecen los mismos eventos para detectar la navegación dentro de sus respectivos ámbitos.

En algunos casos, estos eventos podrían interesar a Page. Por ejemplo, un Page podría controlar el NavigationService.Navigating evento para determinar si se va a cancelar la navegación fuera de sí misma. Esto se muestra en el ejemplo siguiente.

<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

Si registra un controlador con un evento de navegación desde , Pagecomo hace el ejemplo anterior, también debe anular el registro del controlador de eventos. Si no lo hace, puede haber efectos secundarios en cómo la navegación de WPF recuerda las acciones de navegación usando el diario.

Recordatorio de navegación con el diario

WPF usa dos pilas para recordar las páginas desde las que ha navegado: una pila trasera y una pila hacia delante. Al navegar desde el actual Page a un nuevo Page o reenvío a un existente Page, el objeto actual Page se agrega a la pila posterior. Al navegar desde el actual Page al previo Page, el objeto actual Page se agrega a la pila de avance. La pila posterior, la pila hacia delante y la funcionalidad para administrarlas, se conocen colectivamente como diario. Cada elemento de la pila trasera y la pila de reenvío es una instancia de la JournalEntry clase y se conoce como entrada de diario.

Conceptualmente, el diario funciona de la misma manera que lo hacen los botones Atrás y Adelante en Internet Explorer. Se muestran en la ilustración siguiente.

Botones Atrás y Adelante

Para XBAPs hospedados por Internet Explorer, WPF integra el diario en la interfaz de usuario de navegación de Internet Explorer. Esto permite a los usuarios navegar por páginas en un XBAP mediante los botones Atrás, Reenviar y Páginas recientes de Internet Explorer.

Importante

En Internet Explorer, cuando un usuario se aleja y vuelve a un XBAP, solo las entradas del diario para las páginas que no se mantienen activas se conservan en el diario. Para obtener información sobre cómo mantener activas las páginas, consulte Duración de la página y el Diario más adelante en este tema.

De forma predeterminada, el texto de cada Page que aparece en la lista de Páginas recientes de Internet Explorer es el URI de Page. En muchos casos, esto no es especialmente significativo para el usuario. Afortunadamente, puede cambiar el texto mediante una de las siguientes opciones:

  1. Valor del atributo adjunto JournalEntry.Name .

  2. Valor del Page.Title atributo.

  3. Valor Page.WindowTitle del atributo y el URI para el objeto actual Page.

  4. El URI del actual Page. (Valor predeterminado)

El orden en el que se enumeran las opciones coincide con el orden de prioridad para buscar el texto. Por ejemplo, si JournalEntry.Name se establece, se omiten los demás valores.

En el ejemplo siguiente se usa el Page.Title atributo para cambiar el texto que aparece para una entrada de diario.

<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

Aunque un usuario puede navegar por el diario mediante las Atrás, Adelante y páginas Recientes en Internet Explorer, también puede navegar por el diario mediante mecanismos declarativos y programáticos proporcionados por WPF. Una razón para hacerlo es proporcionar interfaces de usuario de navegación personalizadas en las páginas.

Puede agregar soporte para la navegación del diario de manera declarativa utilizando los comandos de navegación expuestos por NavigationCommands. En el ejemplo siguiente se muestra cómo usar el comando de BrowseBack navegación.

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

Puede navegar por el diario mediante programación mediante uno de los siguientes miembros de la NavigationService clase :

El diario también se puede manipular mediante programación, como se describe en Conservar el estado del contenido con el historial de navegación más adelante en este tema.

Vida útil de la página y el diario

Considere un XBAP con varias páginas que contienen contenido enriquecido, incluidos gráficos, animaciones y medios. La superficie de memoria de las páginas como estas podría ser bastante grande, especialmente si se usan medios de audio y vídeo. Dado que el diario "recuerda" las páginas a las que se ha navegado, un XBAP podría consumir rápidamente una gran cantidad de memoria notable.

Por este motivo, el comportamiento predeterminado del diario es almacenar Page metadatos en cada entrada del diario en lugar de una referencia a un Page objeto . Cuando se navega a una entrada de diario, sus Page metadatos se usan para crear una nueva instancia del especificado Page. Como consecuencia, cada Page que se navega tiene la vida útil que se ilustra en la figura siguiente.

Duración de

Aunque el uso del comportamiento predeterminado de registro en diario puede ahorrar en el consumo de memoria, el rendimiento de renderizado por página podría reducirse; reinstanciar un Page puede llevar mucho tiempo, especialmente si tiene mucho contenido. Si necesita conservar una Page instancia en el diario, puede utilizar dos técnicas para hacerlo. En primer lugar, puede navegar mediante programación a objeto Page llamando al método NavigationService.Navigate.

En segundo lugar, puede especificar que WPF conserve una instancia de Page en el diario estableciendo la propiedad KeepAlive a true (el valor predeterminado es false). Como se muestra en el ejemplo siguiente, puede establecer KeepAlive de manera declarativa en el marcado.

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

La duración de un Page que se mantiene activo es sutilmente diferente de uno que no lo está. La primera vez que se navega a un Page que se mantiene activo, se instancia de la misma manera que un Page que no se mantiene activo. Sin embargo, dado que se retiene una instancia de Page en el diario, nunca se vuelve a instanciar mientras permanezca en el diario. Por lo tanto, si Page tiene una lógica de inicialización que necesita ser llamada cada vez que se navega a Page, debería moverla del constructor a un controlador del evento Loaded. Como se muestra en la ilustración siguiente, los eventos Loaded y Unloaded se siguen produciendo cada vez que se navega hacia Page y desde Page, respectivamente.

Cuando se generan eventos cargados y descargados,

Cuando un Page no se mantiene activo, no debe hacer ninguna de las siguientes acciones:

  • Almacene una referencia a ella o cualquier parte de ella.

  • Registre controladores de eventos con eventos no implementados por él.

Si se realiza cualquiera de estas acciones, se crearán referencias que obligan a que Page se conserve en la memoria, incluso después de que se haya eliminado del registro.

En general, debe preferir el comportamiento predeterminado Page de no mantener un Page activo. Sin embargo, esto tiene implicaciones de estado que se describen en la sección siguiente.

Conservar el estado del contenido con el historial de navegación

Si un Page no se mantiene vivo y tiene controles que recopilan datos del usuario, ¿qué ocurre con los datos si el usuario navega fuera y regresa a la Page? Desde la perspectiva de la experiencia del usuario, el usuario debe esperar ver los datos que escribió anteriormente. Desafortunadamente, dado que se crea una nueva instancia de Page con cada navegación, los controles que recopilan los datos se reinstancian y los datos se pierden.

Afortunadamente, el diario proporciona soporte para recordar los datos a través de las Page navegaciones, incluidos los datos de control. En concreto, la entrada del diario para cada Page uno actúa como un contenedor temporal para el estado asociado Page . En los pasos siguientes se describe cómo se usa este soporte cuando se navega desde un Page:

  1. Se añade una entrada para el Page actual al diario.

  2. El estado de Page se almacena con la entrada del diario de esa página, que se agrega a la pila posterior.

  3. Se navega al nuevo Page .

Cuando se vuelve a navegar a la página Page , con el diario, se realizan los pasos siguientes:

  1. Se instancia el Page (la entrada superior del diario en la pila de retroceso).

  2. Page se actualiza con el estado almacenado en la entrada del diario para el Page.

  3. Se ha vuelto a navegar al Page.

WPF usa automáticamente esta compatibilidad cuando se usan los siguientes controles en un Page:

Si usa Page estos controles, los datos introducidos en ellos se recuerdan en todas las Page navegaciones, como se muestra en el colorListBox favorito de la ilustración siguiente.

Página con controles que recuerdan el estado

Cuando un Page tiene controles diferentes a los de la lista anterior, o cuando el estado se almacena en objetos personalizados, debe escribir código para que el diario recuerde el estado a lo largo de las navegaciones Page.

Si necesita recordar pequeños fragmentos de estado a través de las navegaciones Page, puede usar propiedades de dependencia (consulte DependencyProperty) que están configuradas con el indicador de metadatos FrameworkPropertyMetadata.Journal.

Si el estado que su Page necesita recordar entre las navegaciones está conformado por múltiples piezas de datos, podría resultar en un código menos complejo encapsular su estado en una sola clase e implementar la interfaz IProvideCustomContentState.

Si necesita navegar por varios estados de un solo Page sin moverse desde el Page, puede usar IProvideCustomContentState y NavigationService.AddBackEntry.

Galletas

Otra manera de que las aplicaciones de WPF puedan almacenar datos es con cookies, que se crean, actualizan y eliminan mediante los SetCookie métodos y GetCookie . Las cookies que puede crear en WPF son las mismas que usan otros tipos de aplicaciones web; las cookies son fragmentos arbitrarios de datos almacenados por una aplicación en un equipo cliente durante o entre sesiones de aplicación. Los datos de cookies normalmente toman la forma de un par nombre-valor en el formato siguiente.

Nombre=Valor

Cuando los datos se pasan a SetCookie, junto con la Uri de la ubicación para la que se debe establecer la cookie, se crea una cookie en memoria y solo está disponible durante la sesión de aplicación actual. Este tipo de cookie se conoce como cookie de sesión.

Para almacenar una cookie entre sesiones de aplicación, se debe agregar una fecha de expiración a la cookie con el formato siguiente.

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

Una cookie con una fecha de expiración se almacena en la carpeta Archivos temporales de Internet de la instalación de Windows actual hasta que expire la cookie. Esta cookie se conoce como cookie persistente porque persiste en las sesiones de la aplicación.

Para recuperar las cookies de sesión y persistentes, llame al método GetCookie y pase la información Uri sobre la ubicación donde se estableció la cookie con el método SetCookie.

A continuación se muestran algunas de las formas en que se admiten las cookies en WPF:

  • Las aplicaciones independientes de WPF y XBAPs pueden crear y administrar cookies.

  • Se puede acceder a las cookies creadas por un XBAP desde el explorador.

  • Los XBAP del mismo dominio pueden crear y compartir cookies.

  • XBAPs y páginas HTML del mismo dominio pueden crear y compartir cookies.

  • Las cookies se envían cuando XBAP y páginas XAML sueltas realizan solicitudes web.

  • Tanto los XBAPs de nivel superior como los XBAP hospedados en IFRAMES pueden acceder a cookies.

  • La compatibilidad con cookies en WPF es la misma para todos los exploradores compatibles.

  • En Internet Explorer, WPF cumple con la directiva P3P relacionada con las cookies, especialmente en lo que respecta a los XBAP de primera y de terceros.

Navegación estructurada

Si necesita pasar datos de uno Page a otro, puede pasar los datos como argumentos a un constructor sin parámetros de Page. Tenga en cuenta que, si usa esta técnica, debe mantener activo Page ; si no es así, la próxima vez que navegue hasta Page, WPF reinstantia el Page mediante el constructor sin parámetros.

Como alternativa, Page puede implementar propiedades que se establecen con los datos que necesitan ser transmitidos. Sin embargo, las cosas se vuelven complicadas cuando un Page necesita devolver los datos al Page que navegó hacia él. El problema es que la navegación no admite de forma nativa mecanismos para garantizar que se pueda regresar a un elemento Page después de haber navegado desde él. Básicamente, la navegación no admite la semántica de llamada/retorno. Para resolver este problema, WPF proporciona la clase PageFunction<T> que puede usar para asegurarse de que se devuelve un Page de forma predecible y estructurada. Para obtener más información, consulte Información general sobre la navegación estructurada.

La clase NavigationWindow

En este punto, ha visto la gama de servicios de navegación que es más probable que use para desarrollar aplicaciones con contenido navegable. Estos servicios se trataron en el contexto de XBAP, aunque no están limitados a XBAP. Los sistemas operativos modernos y las aplicaciones de Windows aprovechan la experiencia del explorador de los usuarios modernos para incorporar la navegación de estilo explorador en aplicaciones independientes. Algunos ejemplos comunes son:

  • Diccionario de sinónimos de Word: navegue por las opciones de palabras.

  • Explorador de archivos: vaya a archivos y carpetas.

  • Asistentes: Descomponer una tarea compleja en varias páginas que permiten navegar entre ellas. Un ejemplo es el Asistente para componentes de Windows que controla la adición y eliminación de características de Windows.

Para incorporar la navegación de estilo explorador en las aplicaciones independientes, puede usar la NavigationWindow clase . NavigationWindow deriva de Window y lo extiende con la misma compatibilidad con la navegación que proporcionan los XBAP. Puede usar NavigationWindow como ventana principal de la aplicación independiente o como una ventana secundaria, como un cuadro de diálogo.

Para implementar un NavigationWindow, como con la mayoría de las clases de nivel superior en WPF (Window, Page, etc.), se usa una combinación de marcado y code-behind. Esto se muestra en el ejemplo siguiente.

<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

Este código crea un NavigationWindow que navega automáticamente a un Page (HomePage.xaml) cuando se abre el NavigationWindow. NavigationWindow Si es la ventana principal de la aplicación, puede usar el StartupUri atributo para iniciarlo. Esto se muestra en el siguiente código.

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

En la siguiente ilustración se muestra la NavigationWindow como la ventana principal de una aplicación independiente.

Ventana principal

En la ilustración, puede ver que NavigationWindow tiene un título, aunque no se estableció en el NavigationWindow código de implementación del ejemplo anterior. En su lugar, el título se establece mediante la WindowTitle propiedad , que se muestra en el código siguiente.

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

La configuración de las WindowWidth propiedades y WindowHeight también afecta a NavigationWindow.

Normalmente, implementas tú mismo NavigationWindow cuando es necesario personalizar su comportamiento o su apariencia. Si no hace ninguna de las dos, puede usar un atajo. Si especifica el URI del paquete de Page como StartupUri en una aplicación independiente, Application crea automáticamente un NavigationWindow para hospedar el Page. En el marcado siguiente se muestra cómo habilitar esto.

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

Si desea que una ventana de aplicación secundaria, como un cuadro de diálogo, sea un NavigationWindow, puede usar el código del ejemplo siguiente para abrirla.

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

La siguiente imagen muestra el resultado.

A dialog boxUna ventana de navegación como cuadro de diálogo

Como puede ver, NavigationWindow muestra los botones Atrás y Adelante de Internet Explorer que permiten a los usuarios navegar por el diario. Estos botones proporcionan la misma experiencia de usuario, como se muestra en la ilustración siguiente.

Botones Atrás y Adelante en una ventana de navegación

Si sus páginas proporcionan su propia compatibilidad con la navegación del diario y la interfaz de usuario, puede ocultar los botones Atrás y Adelante que se muestran mediante NavigationWindow estableciendo el valor de la propiedad ShowsNavigationUI a false.

Como alternativa, puede usar el soporte para la personalización en WPF para reemplazar la interfaz de usuario de NavigationWindow en sí mismo.

Clase Frame

Tanto el explorador como NavigationWindow son ventanas que hospedan contenido navegable. En algunos casos, las aplicaciones tienen contenido que no necesita hospedarse en una ventana completa. En su lugar, dicho contenido se hospeda dentro de otro contenido. Puede insertar contenido navegable en otro contenido mediante la Frame clase . Frame proporciona la misma compatibilidad que NavigationWindow y XBAPs.

En el ejemplo siguiente se muestra cómo agregar un Frame a un Page mediante el elemento Frame declarativamente.

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

Esta marca establece el atributo Source del elemento Frame con un URI de paquete para el Page al que Frame debe navegar inicialmente. En la siguiente figura se muestra un XBAP con un Page que tiene un Frame y que ha navegado entre varias páginas.

Marco que ha navegado entre varias páginas

No solo debe usar Frame dentro del contenido de un Page. También es habitual hospedar un Frame dentro del contenido de un Window.

De forma predeterminada, Frame solo usa su propio diario en ausencia de otro diario. Si Frame forma parte del contenido hospedado dentro de NavigationWindow o de un XBAP, Frame usa el diario que pertenece a NavigationWindow o a XBAP. A veces, sin embargo, Frame puede necesitar ser responsable de su propio diario. Una razón para hacerlo es permitir la navegación por el diario dentro de las páginas alojadas por un Frame. Esto se muestra en la ilustración siguiente.

Diagrama de marco y página

En este caso, puede configurar el Frame para que use su propio diario estableciendo la propiedad JournalOwnership del Frame en OwnsJournal. Esto se muestra en el siguiente código.

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

En la ilustración siguiente se muestra el efecto de navegar dentro de un Frame que usa su propio diario.

Un marco que utiliza su propio registro

Observe que los asientos del diario se muestran mediante la interfaz de usuario de navegación en el Frame, en lugar de por Internet Explorer.

Nota:

Si un Frame forma parte de contenido que está hospedado en un Window, Frame usa su propio diario y, en consecuencia, muestra su propia interfaz de navegación.

Si la experiencia del usuario requiere que Frame proporcione su propio diario sin mostrar la interfaz de navegación, puede ocultarla configurando NavigationUIVisibility en Hidden. Esto se muestra en el siguiente código.

<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 y NavigationWindow son clases conocidas como hosts de navegación. Un host de navegación es una clase que puede navegar y mostrar contenido. Para ello, cada host de navegación usa su propio NavigationService y diario. La construcción básica de un host de navegación se muestra en la ilustración siguiente.

Diagramas de navegador

Básicamente, esto permite NavigationWindow y Frame proporcionar la misma compatibilidad de navegación que proporciona un XBAP cuando se hospeda en el explorador.

Además de utilizar NavigationService y un diario, los hosts de navegación implementan los mismos componentes que NavigationService. Esto se muestra en la ilustración siguiente.

Un registro en un Marco y en una Ventana de Navegación

Esto le permite programar el apoyo a la navegación directamente contra ellos. Puede considerar esto si necesita proporcionar una interfaz de usuario de navegación personalizada para un Frame que esté hospedado en un Window. Además, ambos tipos implementan miembros adicionales relacionados con la navegación, incluidos BackStack (NavigationWindow.BackStack, Frame.BackStack) y ForwardStack (NavigationWindow.ForwardStack, Frame.ForwardStack), que permiten enumerar las entradas del registro en la pila de retroceso y la pila de avance, respectivamente.

Como se mencionó anteriormente, puede existir más de un diario dentro de una aplicación. En la ilustración siguiente se proporciona un ejemplo de cuándo puede ocurrir esto.

Varios diarios dentro de una aplicación

En este tema, tanto Page como los paquetes XBAP se han usado para demostrar las diversas capacidades de navegación de WPF. Sin embargo, un Page que se compila en una aplicación no es el único tipo de contenido al que se puede navegar, y los XBAPs empaquetados no son la única manera de identificar contenido.

Como se muestra en esta sección, también puedes navegar a archivos XAML sueltos, archivos HTML y objetos.

Un archivo XAML flexible es un archivo con las siguientes características:

  • Contiene solo XAML (es decir, sin código).

  • Tiene una declaración de espacio de nombres adecuada.

  • Tiene la extensión de nombre de archivo .xaml.

Por ejemplo, considere el siguiente contenido que se almacena como un archivo XAML flexible, 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>

Al hacer doble clic en el archivo, el explorador se abre y se desplaza a y muestra el contenido. Esto se muestra en la siguiente ilustración.

Mostrar el contenido en el archivo Person.XAML

Puedes mostrar un archivo XAML flexible desde lo siguiente:

  • Un sitio web en el equipo local, la intranet o Internet.

  • Un recurso compartido de archivos de convención de nomenclatura universal (UNC).

  • Disco duro local.

Se puede agregar un archivo XAML flexible a los favoritos del explorador o ser la página principal del explorador.

Nota:

Para obtener más información sobre cómo publicar e iniciar páginas XAML sueltas, consulta Implementar una aplicación WPF.

Una limitación con respecto a XAML flexible es que solo puedes hospedar contenido que sea seguro para ejecutarse en confianza parcial. Por ejemplo, Window no puede ser el elemento raíz de un archivo XAML flexible. Para obtener más información, vea Seguridad de confianza parcial de WPF.

Como cabría esperar, también puede navegar a HTML. Solo tiene que proporcionar un URI que use el esquema http. Por ejemplo, el código XAML siguiente muestra un Frame objeto que navega a una página HTML.

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

Navegar a HTML requiere permisos especiales. Por ejemplo, no puede navegar desde un XBAP que se ejecuta en el espacio aislado de seguridad de confianza parcial de la zona de Internet. Para obtener más información, vea Seguridad de confianza parcial de WPF.

El WebBrowser control admite el hospedaje de documentos HTML, la navegación y la interoperabilidad con scripts y código administrado. Para obtener información detallada sobre el WebBrowser control, vea WebBrowser.

Al igual que Frame, navegar a HTML mediante WebBrowser requiere permisos especiales. Por ejemplo, desde una aplicación de confianza parcial, solo puede navegar a HTML ubicado en el sitio de origen. Para obtener más información, vea Seguridad de confianza parcial de WPF.

Si tiene datos almacenados como objetos personalizados, una manera de mostrar esos datos es crear un Page con contenido enlazado a esos objetos (consulte Información general sobre el enlace de datos). Si no necesita la sobrecarga de crear una página completa solo para mostrar los objetos, puede navegar directamente a ellos en su lugar.

Tenga en cuenta la Person clase que se implementa en el código siguiente.

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 a él, llame al método NavigationWindow.Navigate como se muestra en el código siguiente.

<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

La siguiente imagen muestra el resultado.

Página que navega a una clase

A partir de esta figura, puede ver que no se muestra nada útil. De hecho, el valor que se muestra es el valor devuelto del ToString método para el objeto Person ; de forma predeterminada, este es el único valor que WPF puede usar para representar el objeto. Puede invalidar el ToString método para devolver información más significativa, aunque solo será un valor de cadena. Una técnica que puede usar que aproveche las funcionalidades de presentación de WPF es usar una plantilla de datos. Puede implementar una plantilla de datos que WPF puede asociar a un objeto de un tipo determinado. El código siguiente muestra una plantilla de datos para el 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>

Aquí, la plantilla de datos está asociada al tipo Person mediante la extensión de marcado x:Type en el atributo DataType. A continuación, la plantilla de datos enlaza TextBlock elementos (vea TextBlock) a las propiedades de la Person clase . En la ilustración siguiente se muestra la apariencia actualizada del Person objeto .

Navegar a una clase que tiene una plantilla de datos

Una ventaja de esta técnica es la coherencia que obtiene al poder reutilizar la plantilla de datos para mostrar los objetos de forma coherente en cualquier lugar de la aplicación.

Para obtener más información sobre las plantillas de datos, consulte Información general sobre plantillas de datos.

Seguridad

La compatibilidad con la navegación de WPF permite que los XBAP se naveguen a través de Internet y permite que las aplicaciones hospeden contenido de terceros. Para proteger tanto las aplicaciones como los usuarios del comportamiento dañino, WPF proporciona una variedad de características de seguridad que se describen en Seguridad y Seguridad de confianza parcial de WPF.

Consulte también