Información general sobre navegación
Windows Presentation Foundation (WPF) admite la navegación de tipo explorador que se puede usar en dos tipos de aplicaciones: aplicaciones independientes y aplicaciones de explorador XAML (XBAP). Para empaquetar el contenido para la navegación, WPF proporciona la clase Page. Puede navegar desde una clase Page a otra mediante declaración con el uso de Hyperlink, o mediante programación, con el uso de NavigationService. WPF usa el diario para recordar las páginas desde las que se navegó o para volver a ellas.
Page, Hyperlink, NavigationService y el diario constituyen la base de la compatibilidad de la navegación que ofrece WPF. Esta introducción describe estas características detalladamente antes de abordar la compatibilidad con la navegación avanzada que incluye navegación a objetos y a archivos Extensible Application Markup Language (XAML) y HTML.
Nota
En este tema, el término "explorador" hace referencia solo a los exploradores que pueden hospedar aplicaciones WPF, lo que actualmente incluye Microsoft Internet Explorer y Firefox. En los casos en que las características específicas de WPF solo sean compatibles con un explorador concreto, se hace referencia a la versión del explorador.
Navegación a aplicaciones para WPF
En este tema se proporciona información general sobre las funcionalidades de navegación clave de WPF. Estas funcionalidades están disponibles tanto para aplicaciones independientes como XBAP, aunque este tema las presenta dentro del contexto de XBAP.
Nota
En este tema no se explica cómo crear e implementar XBAP. Para obtener más información sobre XBAP, consulte Información general sobre las aplicaciones de explorador XAML de WPF.
En esta sección se describen y se muestran los siguientes aspectos de navegación:
Configuración del título, el ancho y el alto de la ventana host
Conservación del estado del contenido con el historial de navegación
Implementación de una página
En WPF, puede navegar a varios tipos de contenido, entre los que se incluyen objetos .NET Framework, objetos personalizados, valores de enumeración, controles de usuario y archivos XAML y HTML. Sin embargo, verá que la manera más cómoda y común de empaquetar contenido es mediante Page. Además, Page implementa características específicas de la navegación para mejorar su apariencia y simplificar el desarrollo.
Con Page, puede implementar mediante declaración una página navegable de contenido XAML con el uso de marcación como se muestra a continuación.
<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />
La clase Page que se implementa en la marcación XAML tiene Page
como elemento raíz y requiere la declaración de espacio de nombres WPF XML. El elemento Page
incluye el contenido al que quiere navegar y que quiere mostrar. Para agregar contenido, establezca el elemento de la propiedad Page.Content
, tal como se muestra en la marcación 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 incluir y redactar el contenido.
Los elementos secundarios de un elemento Page
se consideran como el contenido de Page y, por lo tanto, no es necesario utilizar la declaración explícita Page.Content
. La marcación siguiente es el equivalente declarativo del 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 elemento Page
. Para obtener más información, consulte Modelo de contenido de WPF.
La clase Page solo de marcación es útil para mostrar contenido. Sin embargo, Page también puede mostrar los controles que permiten a los usuarios interactuar con la página, y puede responder a la interacción del usuario al controlar eventos y llamar a la lógica de la aplicación. La clase Page interactiva se implementa mediante una combinación de marcación 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 marcación y un archivo de código subyacente funcionen juntos, se necesita la configuración siguiente:
En el marcado, el elemento
Page
debe incluir el atributox:Class
. Cuando se compila la aplicación, la existencia dex:Class
en el archivo de marcación provoca que Microsoft Build Engine (MSBuild) cree una clasepartial
que deriva de Page y tiene el nombre especificado por el atributox:Class
. Para esto es necesario agregar una declaración de espacio de nombres XML para el esquema XAML (xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
). La clase generadapartial
implementaInitializeComponent
, que se llama para registrar los eventos y establecer las propiedades que se implementan en la marcación.En el código subyacente, la clase debe ser una instancia de
partial
con el mismo nombre especificado mediante el atributox:Class
en el marcado, y debe derivarse de Page. Esto permite que el archivo de código subyacente se asocie a la clasepartial
que se genera para el archivo de marcación cuando se compila la aplicación (consulte Compilar una aplicación de WPF).En el código subyacente, la clase Page debe implementar un constructor que llame al método
InitializeComponent
.InitializeComponent
se implementa mediante la clasepartial
generada por el archivo de marcado para registrar eventos y establecer las propiedades que se definen en el marcado.
Nota
Cuando se agrega una nueva instancia de Page al proyecto con Visual Studio, se implementa Page mediante el marcado y el código subyacente, e incluye la configuración necesaria para crear la asociación entre los archivos de marcado y código subyacente, como se describe aquí.
Una vez tenga una clase Page, podrá navegar a ella. Para especificar la primera clase Page a la que navega una aplicación, debe configurar Page de inicio.
Configuración de una página de inicio
Las aplicaciones XBAP requieren que se hospede una determinada cantidad de infraestructuras de aplicaciones en un explorador. En WPF, la clase Application forma parte de una definición de aplicación que establece la infraestructura de aplicación necesaria (consulte Información general sobre la administración de aplicaciones).
Una definición de aplicación se suele implementar mediante marcación y código subyacente, con el archivo de marcación configurado como un elemento MSBuild ApplicationDefinition
. A continuación, puede ver una definición de aplicación para una aplicación 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
La aplicación XBAP puede usar su definición de aplicación para especificar una clase Page de inicio, que es la clase Page que se carga automáticamente cuando se inicia la aplicación XBAP. Para ello, establezca la propiedad StartupUri con el identificador uniforme de recursos (URI) para la clase Page que quiera.
Nota
En la mayoría de los casos, Page se compila en una aplicación o se implementa con una aplicación. En estos casos, el URI que identifica una clase Page es un URI de paquete, que es un URI que se ajusta al esquema pack. Los URI de paquete se analizan con más detalle en Empaquetar URI en WPF. También puede navegar al contenido con el esquema HTTP, que se describe a continuación.
Puede establecer StartupUri mediante declaración en la marcación, 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 atributo StartupUri
está establecido con un URI de paquete relativo que identifica HomePage.xaml. Cuando se inicia la aplicación XBAP, se navega a HomePage.xaml y se muestra automáticamente. Esto se presenta en la ilustración siguiente, que muestra la aplicación XBAP que se inició desde un servidor web.
Nota
Para obtener más información sobre el desarrollo e implementación de aplicaciones XBAP, consulte Información general sobre las aplicaciones de explorador XAML de WPF e Implementar una aplicación de WPF.
Configuración del título, el ancho y el alto de la ventana host
Algo que quizás haya observado en la ilustración anterior es que el título del explorador y del panel de pestañas es el URI de la aplicación XBAP. Además de largo, el título no es atractivo ni informativo. Por este motivo, Page ofrece una forma de cambiar el título estableciendo la propiedad WindowTitle. Además, puede configurar el ancho y el alto de la ventana del explorador estableciendo WindowWidth y WindowHeight, respectivamente.
WindowTitle, WindowWidth y WindowHeight puede establecerse mediante declaración en la marcación, tal 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.
Navegación por hipervínculos
Una aplicación XBAP típica consta de varias páginas. La manera más sencilla de navegar de una página a otra es usar Hyperlink. Puede agregar mediante declaración una clase Hyperlink a Page mediante el elemento Hyperlink
, que se muestra en la marcación 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 elemento Hyperlink
requiere lo siguiente:
URI de paquete de Page al que se va a navegar, según lo especifica el atributo
NavigateUri
.Contenido al que un usuario puede hacer clic para iniciar la navegación, como texto e imágenes (para averiguar el contenido que el elemento
Hyperlink
puede contener, consulte Hyperlink).
En la siguiente ilustración se muestra una aplicación XBAP con Page que tiene Hyperlink.
Como cabría esperar, si hace clic en Hyperlink, la aplicación XBAP navega a Page que identifica el atributo NavigateUri
. Además, la aplicación XBAP agrega una entrada para la clase anterior Page en la lista Páginas recientes de Internet Explorer. Esto se muestra en la siguiente ilustración.
Además de permitir la navegación de una clase Page a otra, 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 de la clase actual Page u otra clase Page. En WPF, un fragmento de contenido es el contenido que incluye un elemento con nombre. Un elemento con nombre es un elemento que tiene el conjunto de atributos Name
. En la siguiente marcación, se muestra un elemento TextBlock
con nombre 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>
Para que una clase Hyperlink navegue a otro fragmento de contenido, el atributo NavigateUri
debe incluir lo siguiente:
El URI de la clase Page con el fragmento de contenido al que debe navegar.
Un carácter "#".
Nombre del elemento de la clase Page que contiene el fragmento de contenido.
Un URI de fragmento tiene el formato siguiente.
PageURI#
ElementName
A continuación, se muestra un ejemplo de 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 la navegación por fragmentos predeterminada en WPF. WPF también le permite implementar su propio esquema de navegación por fragmentos, que, en parte, requiere la administración del evento NavigationService.FragmentNavigation.
Importante
Puede navegar a fragmentos de páginas dinámicas XAML (archivos XAML de solo marcación con Page
como elemento raíz) solo si se puede navegar por las páginas mediante HTTP.
Sin embargo, una página XAML dinámica puede navegar a sus propios fragmentos.
Servicio de navegación
Mientras que Hyperlink permite que un usuario inicie la navegación a una clase Page concreta, el trabajo de buscar y descargar la página lo realiza la clase NavigationService. Básicamente, NavigationService proporciona la capacidad para procesar una solicitud de navegación en nombre del código de cliente, como Hyperlink. Además, NavigationService implementa compatibilidad de nivel superior para realizar un seguimiento de una solicitud de navegación e influir en ella.
Cuando se hace clic en Hyperlink, WPF llama a NavigationService.Navigate para buscar y descargar Page en el URI de paquete especificado. La clase Page descargada se convierte en un árbol de objetos cuyo objeto raíz es una instancia de la clase Page descargada. Una referencia al objeto raíz Pagese almacena en la propiedad NavigationService.Content. El URI de paquete del contenido al que se navegó se almacena en la propiedad NavigationService.Source, mientras que NavigationService.CurrentSource almacena el URI de paquete de la última página a la que se navegó.
Nota
Una aplicación WPF puede tener más de un elemento NavigationService activo actualmente. Para obtener más información, consulte la sección Hosts de navegación que se encuentra más adelante en este tema.
Navegación programática con el servicio de navegación
No es necesario que obtenga información sobre NavigationService si la navegación se implementa mediante declaración en la marcación con Hyperlink, porque Hyperlink usa NavigationService en su nombre. Esto significa que, siempre que el elemento primario directo o indirecto de Hyperlink sea un host de navegación (consulte Hosts de navegación), Hyperlink será capaz de encontrar y usar el servicio de navegación del host de navegación para procesar una solicitud de navegación.
Sin embargo, existen situaciones en las que es necesario usar NavigationService directamente, así como lo siguiente:
Cuando tenga que crear una instancia de Page con un constructor que no es sin parámetros.
Cuando tenga que establecer propiedades en Page antes de navegar a este.
Cuando la clase Page a la que se deba navegar solo se pueda determinar en tiempo de ejecución.
En estas situaciones, debe escribir código para iniciar la navegación mediante programación llamando al método Navigate del objeto NavigationService. Esto requiere la obtención de NavigationService.
Obtención de 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 un NavigationService. Esto significa que su código debe encontrar una manera de buscar NavigationService, que normalmente es NavigationService que dirigía a la clase Page actual. Puede obtener una referencia a NavigationService llamando al método static
NavigationService.GetNavigationService. Para obtener el elemento NavigationService que navegó a una clase Page concreta, debe pasar una referencia a la clase Page como argumento del método GetNavigationService. El código siguiente muestra cómo obtener el elemento NavigationService para la clase 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 acceso directo para buscar el elemento NavigationService de 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
Page solo puede obtener una referencia a NavigationService cuando Page genera el evento Loaded.
Navegación programática a un objeto de página
En el ejemplo siguiente se muestra cómo se utiliza NavigationService para navegar mediante programación a Page. La navegación programática es necesaria porque solo se pueden crear instantáneas de la clase Page a la que se está navegando mediante un constructor único que no es sin parámetros. Page con el constructor que no es sin parámetros se muestra en la marcación y el código siguientes.
<Page
x:Class="SDKSample.PageWithNonDefaultConstructor"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="PageWithNonDefaultConstructor">
<!-- Content goes here -->
</Page>
using System.Windows.Controls;
namespace SDKSample
{
public partial class PageWithNonDefaultConstructor : Page
{
public PageWithNonDefaultConstructor(string message)
{
InitializeComponent();
this.Content = message;
}
}
}
Namespace SDKSample
Partial Public Class PageWithNonDefaultConstructor
Inherits Page
Public Sub New(ByVal message As String)
InitializeComponent()
Me.Content = message
End Sub
End Class
End Namespace
Page que dirige a Page con el constructor que no es sin parámetros se muestra en la marcación y el código siguientes.
<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 esta clase Page, la navegación se inicia mediante la creación de instantáneas de la clase Page a la que se debe navegar mediante el constructor que no es sin parámetros y una llamada al método NavigationService.Navigate. Navigate acepta una referencia al objeto al que dirigirá NavigationService, en lugar de un URI de paquete.
Navegación programática con Pack URI
Si necesita crear un URI de paquete mediante programación (por ejemplo, solo cuando puede determinar el URI de paquete en tiempo de ejecución), puede usar el método NavigationService.Navigate. 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
Actualización de la página actual
Una clase Page no se descarga si tiene el mismo URI de paquete que el URI de paquete que se almacena en la propiedad NavigationService.Source. Para forzar a que WPF descargue la página actual de nuevo, puede llamar al método NavigationService.Refresh, tal 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
Duración de la navegación
Hay muchas maneras de iniciar la navegación, tal como ha podido ver. Cuando se inicia la navegación, y mientras esta está en curso, puede realizar un seguimiento y dirigirla con los siguientes eventos que se implementan mediante NavigationService:
Navigating. Se produce cuando se solicita una nueva navegación. Puede utilizarse para cancelar la navegación.
NavigationProgress. Se produce periódicamente durante una descarga y ofrece información sobre el progreso de la exploración.
Navigated. Se produce cuando se ha encontrado la página y se ha descargado.
NavigationStopped. Se produce cuando se detiene la navegación (al llamar a StopLoading), o cuando se solicita una nueva navegación mientras hay una navegación en curso.
NavigationFailed. Se produce cuando se genera un error mientras se navega por el contenido solicitado.
LoadCompleted. Se produce cuando el contenido al que se navegó se carga y se analiza, y empieza a representarse.
FragmentNavigation. Se produce cuando se inicia la navegación a un fragmento de contenido, cosa que tiene lugar:
Inmediatamente, si el fragmento deseado está en el contenido actual.
Una vez se ha 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 ilustración siguiente.
En general, estos eventos no afectan a Page. Es más probable que afecten a una aplicación y, por este motivo, estos eventos también los genera la clase Application:
Cada vez que NavigationService genera un evento, la clase Application genera el evento correspondiente. Frame y NavigationWindow ofrecen los mismos eventos para detectar la navegación en sus respectivos ámbitos.
En algunos casos,una clase Page podría estar interesada en estos eventos. Por ejemplo, es posible que Page administre el evento NavigationService.Navigating para determinar si se debe cancelar la navegación fuera de este o no. 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 Page, al igual que en el ejemplo anterior, también debe anular el registro del controlador de eventos. Si no lo hace, pueden producirse efectos secundarios con relación a cómo la navegación WPF recuerda la navegación de Page con el diario.
Registro de la navegación con el diario
WPF usa dos pilas para recordar las páginas desde las que ha navegado: una pila de retroceso y una pila de avance. Cuando navega desde la clase Page actual a una nueva clase Page o avanza hacia una clase Page existente, se agrega la clase Page actual a la pila de retroceso. Cuando retrocede desde la clase Page a la clase Page anterior, se agrega la clase actual Page a la pila de avance. La pila de retroceso, la pila de avance y la funcionalidad para administrarlas se conocen en conjunto como el diario. Cada elemento de la pila de retroceso y la pila de avance es una instancia de la clase JournalEntry y se conoce como una entrada de diario.
Navegación por el diario desde Internet Explorer
Conceptualmente, el diario funciona de la misma forma que los botones Atrás y Adelante en Internet Explorer. Esto se muestra en la siguiente ilustración.
Para las aplicaciones XBAP que hospeda Internet Explorer, WPF integra el diario en la interfaz de usuario de navegación de Internet Explorer. Esto permite a los usuarios navegar por las páginas en una aplicación XBAP mediante el uso de los botones Atrás, Adelante y Páginas recientes de Internet Explorer.
Importante
En Internet Explorer, cuando un usuario sale o vuelve a una aplicación XBAP, solo se retienen en el diario las entradas de las páginas que no se mantuvieron activas. Para obtener información sobre cómo mantener las páginas activas, consulte la sección Duración de la página y el diario más adelante en este tema.
De forma predeterminada, el texto de cada clase Page que aparece en la lista Páginas recientes de Internet Explorer es el URI de la clase Page. En muchos casos, esto no es especialmente significativo para el usuario. Afortunadamente, puede cambiar el texto mediante una de las siguientes opciones:
Valor del atributo
JournalEntry.Name
adjunto.Valor del atributo
Page.Title
.Valor del atributo
Page.WindowTitle
y URI del elemento Page actual.URI del elemento Page actual. (Es el valor predeterminado).
El orden en que se enumeran las opciones coincide con el orden de prioridad para buscar el texto. Por ejemplo, si JournalEntry.Name
está establecido, se omiten los demás valores.
En el ejemplo siguiente se usa el atributo Page.Title
para cambiar el texto que aparece para una entrada del 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
Navegación por el diario mediante WPF
Aunque un usuario puede navegar por el diario mediante los botones Atrás, Adelante y Páginas recientes en Internet Explorer, también puede explorar el diario con los mecanismos declarativos y programáticos que proporciona WPF. Una razón para ello es proporcionar interfaces de usuario de navegación personalizada en las páginas.
Puede agregar compatibilidad de la navegación del diario mediante declaración a través de los comandos de navegación que expone NavigationCommands. En el siguiente ejemplo se muestra cómo se utiliza el comando de navegación BrowseBack
.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.NavigationCommandsPage">
<Hyperlink Command="NavigationCommands.BrowseBack">Back</Hyperlink>
<Hyperlink Command="NavigationCommands.BrowseForward">Forward</Hyperlink>
</Page>
Puede navegar mediante programación por el diario a través de uno de los siguientes miembros de la clase NavigationService:
El diario también se puede manipular mediante programación, como se describe en la sección Conservación del estado del contenido con el historial de navegación más adelante en este tema.
Duración de la página y el diario
Considere una aplicación XBAP con varias páginas que incluyen contenido avanzado, como gráficos, animaciones y elementos multimedia. La superficie de memoria de este tipo de páginas podría ser bastante grande, especialmente si se usan elementos multimedia de audio y vídeo. Dado que el diario "recuerda" las páginas a las que se ha navegado, una aplicación XBAP de este tipo podría consumir rápidamente una cantidad de memoria considerable.
Por este motivo, el comportamiento predeterminado del diario es almacenar los metadatos de Page en cada entrada del diario en lugar de una referencia a un objeto Page. Cuando se navega a una entrada de diario, sus metadatos Page se utilizan para crear una nueva instancia de la clase Page especificada. Como consecuencia, cada clase Page a la que se navega tiene la duración que se muestra en la ilustración siguiente.
Aunque el uso del comportamiento predeterminado de registro en el diario puede ahorrar consumo de memoria, es posible que se reduzca el rendimiento de representación por página; volver a crear una instancia de Page puede llevar mucho tiempo, especialmente si incluye mucho contenido. Si necesita conservar una instancia Page en el diario, puede usar dos técnicas. En primer lugar, puede navegar mediante programación a un 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 en true
(el valor predeterminado es false
). Como se muestra en el ejemplo siguiente, puede establecer KeepAlive mediante declaración en la marcación.
<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 una clase Page que se mantiene activa es ligeramente diferente de una que no se mantiene activa. La primera vez que se navega a una clase Page que se mantiene activa, se crea una instancia de ella como una clase Page que no se mantiene activa. Sin embargo, dado que se conserva una instancia de Page en el diario, nunca se crean instancias de nuevo mientras permanece en el diario. Por consiguiente, si una clase Page tiene una lógica de inicialización que debe llamarse 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 generan cada vez que se navega desde o a Page, respectivamente.
Cuando una clase Page no se mantiene activa, no debería realizar ninguna de las acciones siguientes:
Almacenar una referencia a la base de datos ni ninguna parte de esta.
Registrar controladores de eventos con eventos que no haya implementado.
Estas acciones crearán referencias que harán que la clase Page se conserve en la memoria, incluso después de haberla quitado del diario.
En general, es preferible el comportamiento predeterminado de Page que no mantiene ninguna clase Page activa. Sin embargo, esto conlleva implicaciones de estado que se describen en la sección siguiente.
Conservación del estado del contenido con el historial de navegación
Si una clase Page no se mantiene activa, y tiene controles que recopilan datos del usuario, ¿qué les pasa a los datos si un usuario sale de la clase Page y vuelve a ella? Desde la perspectiva de una experiencia de usuario, el usuario debería ver los datos que especificó anteriormente. Desafortunadamente, dado que se crea una nueva instancia de Page con cada navegación, se vuelve a crear una instancia de los controles que recopilaron los datos y se pierden los datos.
Afortunadamente, el diario proporciona compatibilidad para recordar los datos a través de las navegaciones de Page, incluidos los datos de control. En concreto, la entrada de diario de cada Page actúa como un contenedor temporal para el estado de Page asociado. En los siguientes pasos se describe cómo se usa esta compatibilidad cuando se navega desde Page:
Se agrega al diario una entrada de la clase Page actual.
El estado de la clase Page se almacena con la entrada de diario de esa página, que se agrega a la pila de retroceso.
Se navega a la nueva clase Page.
Cuando se vuelve a navegar a la página Page con el diario, se realizan los pasos siguientes:
Se crea una instancia de Page (la entrada superior del diario en la pila de retroceso).
Se actualiza Page con el estado que se almacenó con la entrada del diario para Page.
Se vuelve a navegar a Page.
WPF usa automáticamente esta compatibilidad cuando se usan los siguientes controles en una clase Page:
Si una clase Page usa estos controles, los datos que se introducen en estos se recuerdan en las navegaciones de Page, como se muestra en la clase ListBox de la ilustración siguiente.
Cuando Page tiene controles distintos de los de la lista anterior, o cuando el estado se almacena en objetos personalizados, debe escribir código que permita al diario recordar el estado entre navegaciones Page.
Si necesita recordar pequeños fragmentos de estado entre navegaciones Page, puede usar las propiedades de dependencia (consulte DependencyProperty) que se configuran con la marca de metadatos FrameworkPropertyMetadata.Journal.
Si el estado que debe recordar Page entre navegaciones consta de varios fragmentos de datos, puede que le parezca que no se necesita tanto código si se encapsula el estado en una sola clase y se implementa la interfaz IProvideCustomContentState.
Si necesita navegar por varios estados de una sola clase Page, sin navegar desde la clase Page, puede usar IProvideCustomContentState y NavigationService.AddBackEntry.
Cookies
Otra forma en que las aplicaciones WPF pueden almacenar datos es con las cookies, que se crean, actualizan y eliminan mediante el uso de los métodos SetCookie y GetCookie. Las cookies que se pueden crear en WPF son las mismas que usan otros tipos de aplicaciones web; las cookies son fragmentos de datos arbitrarios que se almacenan en una aplicación de un equipo cliente durante las sesiones de la aplicación o en estas. Los datos de las cookies normalmente adoptan la forma de un par de nombre-valor en el formato siguiente.
Name=
Value
Cuando los datos se pasan a SetCookie, junto con el Uri de la ubicación para la que se debe establecer la cookie, se crea una cookie en memoria y solo está disponible para la duración de la sesión actual de la aplicación. Este tipo de cookie se conoce como cookie de sesión.
Para almacenar una cookie mediante sesiones de la aplicación, debe agregarse una fecha de expiración para la cookie, con el formato siguiente.
NAME=
VALUE; expires=DAY, DD-MMM-YYYY HH:MM:SS GMT
Se almacena una cookie con una fecha de expiración actual en la carpeta de archivos temporales de Internet de la instalación de Windows hasta que expire. Este tipo de cookie se conoce como cookie persistente porque se conserva entre sesiones de aplicación.
Para recuperar las cookies persistentes y de sesión, llame al método GetCookie y pase el Uri de la ubicación donde se estableció la cookie con el método SetCookie.
A continuación, se muestran algunas de las formas en que las cookies se admiten en WPF:
Las aplicaciones independientes WPF y XBAP pueden crear y administrar cookies.
Las cookies que crea una aplicación XBAP son accesibles desde el explorador.
Las aplicaciones XBAP del mismo dominio pueden crear y compartir cookies.
Las aplicaciones XBAP y las páginas HTML del mismo dominio pueden crear y compartir cookies.
Las cookies se envían cuando las aplicaciones XBAP y las páginas XAML dinámicas realizan solicitudes web.
Tanto las aplicaciones XBAP como las aplicaciones XBAP de nivel superior hospedadas en IFRAMES pueden acceder a las cookies.
La compatibilidad de las cookies en WPF es igual para todos los exploradores compatibles.
En Internet Explorer, WPF respeta la directiva de P3P que pertenece a las cookies, especialmente con respecto a las aplicaciones XBAP propias y de terceros.
Navegación estructurada
Si necesita pasar datos de una clase Page a otra, puede pasarlos como argumentos a un constructor que no es sin parámetros de la clase Page. Tenga en cuenta que, si usa esta técnica, debe mantener la clase Page activa; de lo contrario, la próxima vez que navegue a Page, WPF volverá a crear una instancia de Page mediante el constructor sin parámetros.
Como alternativa, su clase Page puede implementar propiedades que se establecen con los datos que deben pasarse. Sin embargo, todo se complica cuando una clase Page debe volver a pasar datos a la clase Page que navegó a esta. El problema es que la navegación no admite de forma nativa mecanismos para garantizar que una clase Page se devuelva una vez se navegue desde esta. Esencialmente, la navegación no admite la semántica de llamada/devolución. Para resolver este problema, WPF proporciona la clase PageFunction<T> que puede usar para asegurarse de que se devuelve una clase Page de una manera predecible y estructurada. Para obtener más información, consulte Información general sobre la navegación estructurada.
Clase NavigationWindow
En este punto, ha visto la gama de servicios de navegación que probablemente usará para compilar aplicaciones con contenido navegable. Estos servicios se trataron en el contexto de aplicaciones XBAP, aunque no están limitados a aplicaciones XBAP. Los sistemas operativos modernos y las aplicaciones de Windows aprovechan la experiencia de exploración de los usuarios modernos para incorporar la navegación de tipo explorador en aplicaciones independientes. Algunos ejemplos frecuentes son:
Diccionario de sinónimos de Word: navegación por las opciones de Word.
Explorador de archivos: navegación por archivos y carpetas.
Asistentes: desglose de una tarea compleja en varias páginas entre las que se puede navegar. 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 tipo explorador en sus aplicaciones independientes, puede usar la clase NavigationWindow. El elemento NavigationWindow deriva de Window y lo extiende con la misma compatibilidad para la navegación que proporcionan las aplicaciones XBAP. Puede usar NavigationWindow como ventana principal de la aplicación independiente o como una ventana secundaria, por ejemplo, un cuadro de diálogo.
Para implementar un elemento NavigationWindow, al igual que con la mayoría de clases de nivel superior en WPF (Window, Page, etc.), use una combinación de marcación y código subyacente. 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 elemento NavigationWindow que navega automáticamente a una clase Page (HomePage.xaml) cuando se abre el elemento NavigationWindow. Si el elemento NavigationWindow es la ventana principal de la aplicación, puede usar el atributo StartupUri
para iniciarlo. Esto se muestra en la marcación siguiente.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="MainWindow.xaml" />
En la siguiente ilustración se muestra el elemento NavigationWindow como ventana principal de una aplicación independiente.
En la ilustración, puede ver que el elemento NavigationWindow tiene un título, aunque no se estableció en el código de implementación del elemento NavigationWindow del ejemplo anterior. En su lugar, el título se establece mediante la propiedad WindowTitle, que se muestra en el siguiente código.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
Title="Home Page"
WindowTitle="NavigationWindow">
</Page>
La configuración de las propiedades WindowWidth y WindowHeight también afecta al elemento NavigationWindow.
Normalmente, deberá implementar su propio elemento NavigationWindow cuando necesite personalizar su comportamiento o su apariencia. Si no realiza nada, puede usar un acceso directo. Si especifica el URI de paquete de una clase Page como StartupUri en una aplicación independiente, el elemento Application crea automáticamente un elemento NavigationWindow para hospedar la clase Page. En la marcación siguiente se muestra cómo habilitar esta opción.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="HomePage.xaml" />
Si quiere que una ventana de la aplicación secundaria, como un cuadro de diálogo, sea un elemento NavigationWindow, puede utilizar 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()
En la figura siguiente se muestra el resultado.
Como puede observar, NavigationWindow muestra los botones Atrás y Adelante de tipo 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.
Si sus páginas proporcionan su propia compatibilidad de navegación por el diario e interfaz de usuario, puede ocultar los botones Atrás y Adelante que muestra NavigationWindow estableciendo el valor de la propiedad ShowsNavigationUI en false
.
Como alternativa, puede usar la compatibilidad con la personalización en WPF para reemplazar la interfaz de usuario de NavigationWindow.
Clase Frame
Tanto el explorador como NavigationWindow son ventanas que hospedan contenido navegable. En algunos casos, las aplicaciones tienen contenido que no hace falta que los hospede una ventana completa. En su lugar, dicho contenido se hospeda dentro de otro contenido. Puede insertar contenido navegable en otro contenido utilizando la clase Frame. Frame proporciona la misma compatibilidad que NavigationWindow y aplicaciones XBAP.
En el ejemplo siguiente se muestra cómo agregar Frame a Page mediante declaración con el uso del 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>
Esta marcación establece el atributo Source
del elemento Frame
con un URI de paquete para Pageal que Frame debe navegar inicialmente. En la siguiente ilustración se muestra una aplicación XBAP con Page que tiene Frame que ha navegado entre varias páginas.
No solo debe usar Frame dentro del contenido de Page. También es común hospedar Frame dentro del contenido de Window.
De forma predeterminada, Frame solo usa su propio diario en ausencia de otro. Si Frame forma parte de contenido que se hospeda dentro de NavigationWindow o una aplicación XBAP, Frame usa el diario que pertenece a NavigationWindow o a la aplicación XBAP. Sin embargo, a veces, es posible que Frame deba ser responsable de su propio diario. Una razón para ello es permitir la navegación del diario dentro de las páginas que se hospedan en Frame. Esto se muestra en la ilustración siguiente.
En este caso, puede configurar Frame para utilizar su propio diario estableciendo la propiedad JournalOwnership de Frame en OwnsJournal. Esto se muestra en la marcación siguiente.
<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 Frame que usa su propio diario.
Observe que las entradas del diario se muestran mediante la interfaz de usuario de navegación en Frame, en lugar de Internet Explorer.
Nota
Si Frame forma parte del contenido que se hospeda en Window, Frame usa su propio diario y, por lo tanto, muestra su propia interfaz de usuario de navegación.
Si la experiencia de usuario requiere Frame para proporcionar su propio diario sin mostrar la interfaz de usuario de navegación, puede ocultar la interfaz de usuario de navegación estableciendo NavigationUIVisibility en Hidden. Esto se muestra en la marcación siguiente.
<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>
Hosts de navegación
Frame y NavigationWindow son clases que se conocen como hosts de navegación. Un host de navegación es una clase a la que se puede navegar y que puede mostrar el contenido. Para lograr esto, cada host de navegación usa su propio NavigationService y diario. La construcción de un host de navegación básica se muestra en la ilustración siguiente.
En esencia, esto permite a NavigationWindow y Frame proporcionar la misma compatibilidad de navegación que proporciona una aplicación XBAP cuando se hospeda en el explorador.
Además de usar NavigationService y un diario, los hosts de navegación implementan los mismos miembros que implementa NavigationService. Esto se muestra en la ilustración siguiente.
Esto le permite programar la compatibilidad con la navegación directamente con ellos. Puede considerar esta opción si necesita proporcionar una interfaz de usuario de navegación personalizada para Frame que se hospeda en 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 le permiten enumerar las entradas del diario en la pila de retroceso y avance, respectivamente.
Como se mencionó anteriormente, pueden haber varios diarios dentro de una aplicación. En la siguiente ilustración se muestra un ejemplo de cuándo ocurre esto.
Navegar a contenido distinto de páginas XAML
En este tema, se han usado Page y aplicaciones XBAP de paquete para demostrar las distintas funcionalidades de navegación de WPF. Sin embargo, Page que se compila en una aplicación no es el único tipo de contenido al que se puede navegar, y las aplicaciones XBAP de paquete no son la única manera de identificar contenido.
Como se muestra en esta sección, también puede desplazarse a archivos XAML y HTML y objetos.
Navegación por archivos XAML dinámicos
Un archivo XAML dinámico es un archivo con las siguientes características:
Solo contiene XAML (es decir, nada de 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 dinámico, 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 al contenido y lo muestra. Esto se muestra en la siguiente ilustración.
Se puede mostrar un archivo XAML dinámico de lo siguiente:
Un sitio web en la máquina local, la intranet o Internet.
Un recurso compartido de archivos de convención de nomenclatura universal (UNC).
El disco local.
Un archivo XAML se puede agregar a los favoritos del explorador, o ser la página principal del explorador.
Nota
Para obtener más información acerca de cómo publicar e iniciar páginas XAML dinámicas, consulte Implementar una aplicación de WPF.
Una limitación con respecto a un archivo XAML dinámico es que solo puede hospedar contenido que sea seguro de ejecutar en confianza parcial. Por ejemplo, Window
no puede ser el elemento raíz de un archivo XAML dinámico. Para obtener más información, vea Seguridad de confianza parcial de WPF.
Navegación a archivos HTML mediante Frame
Como cabría esperar, también puede navegar a HTML. Simplemente, debe proporcionar un URI que usa el esquema HTTP. Por ejemplo, el siguiente XAML muestra Frame 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 una aplicación 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.
Navegación a archivos HTML mediante el Control WebBrowser
El control WebBrowser admite la interoperabilidad de código administrado o script, la navegación y el hospedaje de documentos HTML. Para obtener información detallada sobre el control WebBrowser, consulte WebBrowser.
Al igual que Frame, navegar a HTML mediante WebBrowser requiere permisos especiales. Por ejemplo, desde una aplicación de confianza parcial, puede navegar solo a HTML ubicado en el sitio de origen. Para obtener más información, vea Seguridad de confianza parcial de WPF.
Navegación por objetos personalizados
Si tiene datos que se almacenan como objetos personalizados, una manera de mostrar los datos consiste en crear Page con el contenido que está enlazado a esos objetos (vea Información general sobre el enlace de datos). Si no necesita la sobrecarga de la creación de una página completa para mostrar los objetos, puede navegar directamente a ellos en su lugar.
Tenga en cuenta la clase Person
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 ella, llame al método NavigationWindow.Navigate, como se muestra en el siguiente código.
<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
En la figura siguiente se muestra el resultado.
En esta ilustración, puede ver que no se muestra nada útil. De hecho, el valor que se muestra es el valor devuelto del método ToString
para el objeto Person; de forma predeterminada, este es el único valor que WPF puede usar para representar el objeto. Podría invalidar el método ToString
para devolver información más significativa, aunque seguirá siendo solo un valor de cadena. Una técnica que aprovecha las funcionalidades de presentación de WPF es el uso de una plantilla de datos. Puede implementar una plantilla de datos que WPF puede asociar a un objeto de un tipo determinado. En el código siguiente se muestra una plantilla de datos para el 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>
En este caso, la plantilla de datos está asociada al tipo Person
mediante la extensión de marcación x:Type
del atributo DataType
. A continuación, la plantilla de datos enlaza los elementos TextBlock
(consulte TextBlock) a las propiedades de la clase Person
. En la siguiente ilustración se muestra el aspecto actualizado del objeto Person
.
Una ventaja de esta técnica es la coherencia que obtiene al poder volver a usar la plantilla de datos para mostrar los objetos de forma coherente en cualquier parte de la aplicación.
Para obtener más información, consulte Información general sobre plantillas de datos.
Seguridad
La compatibilidad de navegación de WPF permite navegar a las aplicaciones XBAP a través de Internet, y que las aplicaciones hospeden contenido de terceros. Para proteger las aplicaciones y los usuarios de un comportamiento malintencionado, WPF proporciona una variedad de características de seguridad que se describen en Seguridad y Seguridad de confianza parcial de WPF.
Vea también
.NET Desktop feedback