Información general sobre la navegación estructurada
Actualización: noviembre 2007
El contenido que puede ser hospedado por Aplicación del explorador XAML (XBAP), un objeto Frame o un objeto NavigationWindow se compone de páginas que pueden ser identificadas por identificadores de recursos uniformes (URIs) paquete y a las que se puede navegar mediante hipervínculos. La estructura de las páginas y las maneras en las que se pueden navegar, tal como las definen los hipervínculos, se conocen como la topología de navegación. Este tipo de topología satisface diversos tipos de aplicación, particularmente aquéllas que navegan por documentos. Para tales aplicaciones, el usuario puede navegar de una página a otra sin que ninguna de ellas necesite saber nada sobre la otra.
Sin embargo, otros tipos de aplicaciones tienen páginas que necesitan saber cuándo se ha navegado entre ellas. Por ejemplo, considere una aplicación de recursos humanos que tenga una página con la lista de todos los empleados de la organización, la página "Lista de empleados". Esta página también podría permitir a los usuarios agregar un nuevo empleado haciendo clic en un hipervínculo. Cuando se hace clic, la página navega a una página "Agregar un empleado", para recopilar los detalles del nuevo empleado y devolverlos a la página "Lista de empleados", para crear el nuevo empleado y actualizar la lista. Este estilo de navegación es similar a llamar a un método para realizar algún procesamiento y devolver un valor, lo que se considera programación estructurada. Como tal, este estilo de navegación se conoce como navegación estructurada.
La clase Page no implementa compatibilidad con la navegación estructurada. En su lugar, la clase PageFunction<T> deriva de Page y la amplía extiende con las estructuras básicas requeridas para la navegación estructurada. En este tema se muestra cómo establecer navegación estructurada mediante PageFunction<T>.
Nota
El ejemplo incorporado a esta información general procede de Ejemplo Structured Navigation.
Este tema contiene las secciones siguientes.
- Navegación estructurada
- Navegación estructurada con PageFunction
- Otros tipos de navegación estructurada
- Temas relacionados
Navegación estructurada
Cuando una página llama a otra página en una navegación estructurada, se requieren algunos o todos los comportamientos siguientes:
La página que llama navega a la página llamada, con la opción de pasar parámetros requeridos por la página llamada.
La página llamada, cuando un usuario ha terminado de usar la página que llama, puede devolver específicamente a la página de llamada lo siguiente:
Devolución de información de estado, que describe cómo se completó la página que llama (por ejemplo, si un usuario presionó un botón Aceptar o un botón Cancelar).
Devolución de los datos recopilados del usuario (por ejemplo, los detalles del nuevo empleado).
Cuando la página que llama vuelve a la página llamada, la página llamada se quita del historial de navegación, para aislar cada instancia de la página llamada.
En la figura siguiente se muestran estos comportamientos.
Puede implementar estos comportamientos utilizando un objeto PageFunction<T> como página llamada.
Navegación estructurada con PageFunction
En este tema se muestra cómo implementar los mecanismos básicos de navegación estructurada que implica un objeto PageFunction<T>único. En este ejemplo, un objeto Page llama a un objeto PageFunction<T> para recibir un valor String del usuario y devolverlo.
Crear una página que llama
La página que llama a PageFunction<T> puede ser un objeto Page o un objeto PageFunction<T>. En este ejemplo, es un objeto Page, como se muestra en el código siguiente.
<Page
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
x:Class="StructuredNavigationSample.CallingPage"
WindowTitle="Calling Page"
WindowWidth="250" WindowHeight="150">
...
</Page>
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler, Visibility
Imports System.Windows.Controls ' Page
Imports System.Windows.Navigation ' ReturnEventArgs
Namespace StructuredNavigationSample
Public Class CallingPage
Inherits Page
Public Sub New()
Me.InitializeComponent()
...
End Sub
...
End Class
End Namespace
using System.Windows; // RoutedEventArgs, RoutedEventHandler, Visibility
using System.Windows.Controls; // Page
using System.Windows.Navigation; // ReturnEventArgs
namespace StructuredNavigationSample
{
public partial class CallingPage : Page
{
public CallingPage()
{
InitializeComponent();
...
}
...
}
}
Crear una función de la página para la llamada
Dado que la página que llama puede utilizar la página llamada para recopilar y devolver datos del usuario, PageFunction<T> se implementa como una clase genérica cuyo argumento de tipo especifica el tipo del valor que devolverá la página llamada. En el código siguiente se muestra la implementación inicial de la página llamada, utilizando un objeto PageFunction<T>, que devuelve un objeto String.
<PageFunction
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
x:Class="StructuredNavigationSample.CalledPageFunction"
x:TypeArguments="sys:String"
Title="Page Function"
WindowWidth="250" WindowHeight="150">
<Grid Margin="10">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<!-- Data -->
<Label Grid.Column="0" Grid.Row="0">DataItem1:</Label>
<TextBox Grid.Column="1" Grid.Row="0" Name="dataItem1TextBox"></TextBox>
<!-- Accept/Cancel buttons -->
<TextBlock Grid.Column="1" Grid.Row="1" HorizontalAlignment="Right">
<Button Name="okButton" IsDefault="True" MinWidth="50">OK</Button>
<Button Name="cancelButton" IsCancel="True" MinWidth="50">Cancel</Button>
</TextBlock>
</Grid>
</PageFunction>
Imports System ' String
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler
Imports System.Windows.Navigation ' PageFunction
Namespace StructuredNavigationSample
Public Class CalledPageFunction
Inherits PageFunction(Of String)
Public Sub New()
Me.InitializeComponent()
End Sub
...
End Class
End Namespace
using System; // String
using System.Windows; // RoutedEventArgs, RoutedEventHandler
using System.Windows.Navigation; // PageFunction
namespace StructuredNavigationSample
{
public partial class CalledPageFunction : PageFunction<String>
{
public CalledPageFunction()
{
InitializeComponent();
}
...
}
}
La declaración de un objeto PageFunction<T> es similar a la declaración de un objeto Page con la adición de los argumentos de tipo. Como puede ver en código de ejemplo, los argumentos de tipo se especifican tanto en el marcado XAML, utilizando el atributo x:TypeArguments, como en el código subyacente, utilizando la sintaxis de argumento de tipo genérico estándar.
No tiene que utilizar solamente clases .NET Framework como argumentos de tipo. Se podría llamar a un objeto PageFunction<T> para recopilar datos específicos de dominio que se resuman como un tipo personalizado. El código siguiente muestra cómo utilizar un tipo personalizado como argumento de tipo para un objeto PageFunction<T>.
Los argumentos de tipo para el objeto PageFunction<T> proporcionan la base para la comunicación entre una página que llama y la página llamada, que se explican en las secciones siguientes.
Como verá, el tipo que se identifica con la declaración de un objeto PageFunction<T> desempeña un papel importante en la devolución de datos de un objeto PageFunction<T> a la página que llama.
Llamar a PageFunction y pasar parámetros
Para llamar a una página, la página que llama debe crear instancias de la página llamada y navegar a ellas utilizando el método Navigate. Esto permite que la página que llama pase datos iniciales a la página llamada, tales como valores predeterminados para los datos recopilados por la página llamada.
El código siguiente muestra la página que llama con un constructor no predeterminado para aceptar parámetros de la página que llama.
Imports System ' String
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler
Imports System.Windows.Navigation ' PageFunction
Namespace StructuredNavigationSample
Public Class CalledPageFunction
Inherits PageFunction(Of String)
...
Public Sub New(ByVal initialDataItem1Value As String)
Me.InitializeComponent()
...
' Set initial value
Me.dataItem1TextBox.Text = initialDataItem1Value
End Sub
...
End Class
End Namespace
using System; // String
using System.Windows; // RoutedEventArgs, RoutedEventHandler
using System.Windows.Navigation; // PageFunction
namespace StructuredNavigationSample
{
public partial class CalledPageFunction : PageFunction<String>
{
...
public CalledPageFunction(string initialDataItem1Value)
{
InitializeComponent();
...
// Set initial value
this.dataItem1TextBox.Text = initialDataItem1Value;
}
En el código siguiente e muestra la página que llama administrando el evento Click del objeto Hyperlink declarado anteriormente para crear instancias de la página llamada y pasarle un valor de cadena inicial.
Imports System ' String
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler
Imports System.Windows.Navigation ' PageFunction
Namespace StructuredNavigationSample
Public Class CalledPageFunction
Inherits PageFunction(Of String)
...
Public Sub New(ByVal initialDataItem1Value As String)
Me.InitializeComponent()
...
' Set initial value
Me.dataItem1TextBox.Text = initialDataItem1Value
End Sub
...
End Class
End Namespace
using System; // String
using System.Windows; // RoutedEventArgs, RoutedEventHandler
using System.Windows.Navigation; // PageFunction
namespace StructuredNavigationSample
{
public partial class CalledPageFunction : PageFunction<String>
{
...
public CalledPageFunction(string initialDataItem1Value)
{
InitializeComponent();
...
// Set initial value
this.dataItem1TextBox.Text = initialDataItem1Value;
}
No es obligatorio pasar parámetros a la página llamada. En su lugar, podría hacer lo siguiente:
En la página que llama:
Cree una instancia de la clase PageFunction<T> llamada utilizando el constructor predeterminado.
Almacene los parámetros en Properties.
Navegue al objeto PageFunction<T> llamado.
En el objeto PageFunction<T> llamado:
- Recupere y utilice los parámetros almacenados en Properties.
Sin embargo, como verá pronto, todavía necesitará utilizar código para crear instancias y navegar a la página llamada para recopilar los datos devueltos por la página llamada. Por esta razón, PageFunction<T> necesita mantenerse vivo; de lo contrario, la próxima vez que navegue al objeto PageFunction<T>, WPF creará una instancia de PageFunction<T> utilizando el constructor predeterminado.
Para que la página llamada puede volver, sin embargo, necesita devolver datos que puedan ser recuperados por la página que llama.
Devolver el resultado y los datos de una tarea a una página que llama
Cuando el usuario ha terminado de utilizar la página llamada, lo que sucede en este ejemplo al presionar los botones Aceptar o Cancelar, la página llamada debe volver. Puesto que la página que llama utilizó la página llamada para recopilar los datos del usuario, la página que llama requiere dos tipos de información:
Si el usuario canceló la página llamada (presionando el botón Aceptar o el botón Cancelar en este ejemplo). Esto permite decidir a la página que llama si debe procesar los datos que la página de llamada recopiló del usuario.
Los datos que proporcionó el usuario.
Para devolver información, PageFunction<T> implementa el método OnReturn. En el código siguiente se muestra cómo llamarlo.
Imports System ' String
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler
Imports System.Windows.Navigation ' PageFunction
Namespace StructuredNavigationSample
Public Class CalledPageFunction
Inherits PageFunction(Of String)
...
Private Sub okButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Accept when Ok button is clicked
Me.OnReturn(New ReturnEventArgs(Of String)(Me.dataItem1TextBox.Text))
End Sub
Private Sub cancelButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Cancel
Me.OnReturn(Nothing)
End Sub
End Class
End Namespace
using System; // String
using System.Windows; // RoutedEventArgs, RoutedEventHandler
using System.Windows.Navigation; // PageFunction
namespace StructuredNavigationSample
{
public partial class CalledPageFunction : PageFunction<String>
{
...
void okButton_Click(object sender, RoutedEventArgs e)
{
// Accept when Ok button is clicked
OnReturn(new ReturnEventArgs<string>(this.dataItem1TextBox.Text));
}
void cancelButton_Click(object sender, RoutedEventArgs e)
{
// Cancel
OnReturn(null);
}
}
}
En este ejemplo, si un usuario presiona el botón Cancelar, se devuelve un valor de null a la página de llamada. Si en su lugar se presiona el botón Aceptar, se devuelve el valor de cadena proporcionado por el usuario. OnReturn es un método protectedvirtual al que llama para devolver los datos a la página que llama. Los datos deben empaquetarse en una instancia del tipo ReturnEventArgs<T> genérico, cuyo argumento de tipo especifica el tipo de valor que devuelve Result. De esta manera, al declarar PageFunction<T> con un argumento de tipo determinado, se está indicando que PageFunction<T> devolverá una instancia del tipo que especificado por el argumento de tipo. En este ejemplo, el argumento de tipo y, por consiguiente, el valor devuelto son del tipo String.
Cuando se llama a OnReturn, la página que llama necesita alguna manera de recibir el valor devuelto de l objeto PageFunction<T>. Por esta razón, PageFunction<T> implementa el evento Return para llamar páginas para administrar. Cuando se llama a OnReturn, de produce Return, de modo que la página que llama se puede registrar en Return para recibir la notificación.
Imports System.Windows ' RoutedEventArgs, RoutedEventHandler, Visibility
Imports System.Windows.Controls ' Page
Imports System.Windows.Navigation ' ReturnEventArgs
Namespace StructuredNavigationSample
Public Class CallingPage
Inherits Page
...
Private Sub pageFunctionHyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
' Instantiate and navigate to page function
Dim calledPageFunction As New CalledPageFunction("Initial Data Item Value")
AddHandler calledPageFunction.Return, New ReturnEventHandler(Of String)(AddressOf Me.calledPageFunction_Return)
MyBase.NavigationService.Navigate(calledPageFunction)
End Sub
Private Sub calledPageFunction_Return(ByVal sender As Object, ByVal e As ReturnEventArgs(Of String))
Me.pageFunctionResultsTextBlock.Visibility = Windows.Visibility.Visible
' Display result
Me.pageFunctionResultsTextBlock.Text = IIf((Not e Is Nothing), "Accepted", "Canceled")
' If page function returned, display result and data
If (Not e Is Nothing) Then
Me.pageFunctionResultsTextBlock.Text = (Me.pageFunctionResultsTextBlock.Text & ChrW(10) & e.Result)
End If
End Sub
End Class
End Namespace
using System.Windows; // RoutedEventArgs, RoutedEventHandler, Visibility
using System.Windows.Controls; // Page
using System.Windows.Navigation; // ReturnEventArgs
namespace StructuredNavigationSample
{
public partial class CallingPage : Page
{
...
void pageFunctionHyperlink_Click(object sender, RoutedEventArgs e)
{
// Instantiate and navigate to page function
CalledPageFunction CalledPageFunction = new CalledPageFunction("Initial Data Item Value");
CalledPageFunction.Return += pageFunction_Return;
this.NavigationService.Navigate(CalledPageFunction);
}
void pageFunction_Return(object sender, ReturnEventArgs<string> e)
{
this.pageFunctionResultsTextBlock.Visibility = Visibility.Visible;
// Display result
this.pageFunctionResultsTextBlock.Text = (e != null ? "Accepted" : "Canceled");
// If page function returned, display result and data
if (e != null)
{
this.pageFunctionResultsTextBlock.Text += "\n" + e.Result;
}
}
}
}
Quitar páginas de tarea cuando se completa una tarea
Cuando vuelve una página llamada y el usuario no la canceló, la página de llamada procesa los datos proporcionados por el usuario y también los devueltos desde la página llamada. La adquisición de datos de esta manera suele ser una actividad aislada; cuando vuelve la página llamada, la página que llama debe crear y navegar a una nueva página que llama para capturar más datos.
Sin embargo, a menos que la página llamada se quite del diario, el usuario podrá volver a una instancia anterior de la página que llama. Si un objeto PageFunction<T> se retiene en el diario está determinado por la propiedad RemoveFromJournal. De forma predeterminada, una función de página se quita automáticamente cuando se llama a OnReturn, porque RemoveFromJournal se establece en true. Para mantener una función de página en el historial de navegación después de llamar a OnReturn, establezca RemoveFromJournal en false.
Otros tipos de navegación estructurada
En este tema se muestra el uso más básico de un objeto PageFunction<T> para permitir la navegación estructurada de llamada/retorno. Esta base proporciona la capacidad de crear más tipos complejos de navegación estructurada.
Por ejemplo, hay ocasiones en las que una página que llama necesita varias páginas para recopilar suficientes datos de un usuario o para realizar una tarea. El uso de varias páginas se conoce como un "asistente". Para obtener más información sobre los asistentes, vea Ejemplo Wizard.
En otros casos, las aplicaciones pueden tener topologías de navegación complejas que dependen de la navegación estructurada para funcionar eficazmente. Para obtener más información, consulte Información general sobre topologías de navegación.
Vea también
Tareas
Conceptos
Información general sobre topologías de navegación