Compartir a través de


Introducción a la navegación estructurada

El contenido que se puede hospedar en una aplicación del explorador XAML (XBAP), un Frame, o un NavigationWindow se compone de páginas que se pueden identificar mediante identificadores uniformes de recursos (URI) del paquete y que se navegan a través de hipervínculos. La estructura de las páginas y las formas en que se pueden navegar, tal como se definen en los hipervínculos, se conoce como topología de navegación. Esta topología se adapta a una variedad de tipos de aplicación, especialmente aquellos que navegan por documentos. Para estas aplicaciones, el usuario puede navegar de una página a otra sin necesidad de conocer nada sobre el otro.

Sin embargo, otros tipos de aplicaciones tienen páginas que necesitan saber cuándo se han navegado entre ellos. Por ejemplo, considere una aplicación de recursos humanos que tiene una página para enumerar todos los empleados de una organización, la página "Enumerar empleados". Esta página también podría permitir que los usuarios agreguen un nuevo empleado haciendo clic en un hipervínculo. Cuando se hace clic en él, la página navega a una página "Agregar un empleado" para recopilar los detalles del nuevo empleado y devolverlos a la página "Enumerar 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, que se conoce como programación estructurada. Por lo tanto, este estilo de navegación se conoce como navegación estructurada.

La Page clase no implementa compatibilidad con la navegación estructurada. En su lugar, la PageFunction<T> clase deriva de Page y la extiende con las construcciones básicas necesarias para la navegación estructurada. En este tema se muestra cómo establecer la navegación estructurada mediante PageFunction<T>.

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 realiza la llamada navega a la página llamada y, opcionalmente, pasa parámetros requeridos por la página llamada.

  • La página llamada, cuando un usuario ha terminado de utilizarla, regresa específicamente a la página de origen, de manera opcional.

    • Devolver información de estado que describe cómo se completó la página de llamada (por ejemplo, si un usuario presionaba un botón Aceptar o un botón Cancelar).

    • Devolver esos datos que se recopilaron del usuario (por ejemplo, detalles de nuevos empleados).

  • Cuando la página que realiza la llamada vuelve a la página llamada, la página llamada se quita del historial de navegación para aislar una instancia de una página llamada de otra.

Estos comportamientos se muestran en la ilustración siguiente:

Captura de pantalla que muestra el flujo entre la página de llamada y la página llamada.

Puede implementar estos comportamientos mediante un elemento PageFunction<T> como la página llamada.

Navegación estructurada con PageFunction

En este tema se muestra cómo implementar la mecánica básica de la navegación estructurada que implica un único PageFunction<T>. En este ejemplo, un Page llama a un PageFunction<T> para obtener un valor String del usuario y devolverlo.

Creación de una página de llamada

La página que llama a PageFunction<T> puede ser una Page o una PageFunction<T>. En este ejemplo, es un Page, 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="StructuredNavigationSample.CallingPage"
    WindowTitle="Calling Page" 
    WindowWidth="250" WindowHeight="150">
</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace StructuredNavigationSample
{
    public partial class CallingPage : Page
    {
        public CallingPage()
        {
            InitializeComponent();
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Navigation

Namespace StructuredNavigationSample

Public Class CallingPage
    Inherits Page
    Public Sub New()
        Me.InitializeComponent()
}
End Sub
    }
}
End Class

End Namespace

Crear una función de la página para llamar

Dado que la página de llamada puede usar 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, mediante un PageFunction<T>, que devuelve un String.

<PageFunction
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://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>
using System;
using System.Windows;
using System.Windows.Navigation;

namespace StructuredNavigationSample
{
    public partial class CalledPageFunction : PageFunction<String>
    {
        public CalledPageFunction()
        {
            InitializeComponent();
        }
Imports System.Windows
Imports System.Windows.Navigation

Namespace StructuredNavigationSample

Public Class CalledPageFunction
    Inherits PageFunction(Of String)
    Public Sub New()
        Me.InitializeComponent()
    End Sub
    }
}
End Class

End Namespace

La declaración de PageFunction<T> es similar a la declaración de Page con la adición de los argumentos de tipo. Como puede ver en el ejemplo de código, los argumentos de tipo se especifican tanto en el marcado XAML, usando el atributo x:TypeArguments, como en el código subyacente, mediante la sintaxis estándar de argumento de tipo genérico.

No tiene que usar solo clases de .NET Framework como argumentos de tipo. PageFunction<T> podría llamarse para recopilar datos específicos del dominio que se abstraen como un tipo personalizado. En el código siguiente se muestra cómo usar un tipo personalizado como argumento de tipo para .PageFunction<T>

namespace SDKSample
{
    public class CustomType
    {
Public Class CustomType
    }
}
End Class
<PageFunction
    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.CustomTypePageFunction"
    x:TypeArguments="local:CustomType">
</PageFunction>
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class CustomTypePageFunction : PageFunction<CustomType>
    {
Partial Public Class CustomTypePageFunction
    Inherits System.Windows.Navigation.PageFunction(Of CustomType)
    }
}
End Class

Los argumentos de tipo de PageFunction<T> proporcionan la base para la comunicación entre una página que llama y la página llamada, que se describen en las secciones siguientes.

Como podrás ver, el tipo que se identifica con la declaración de un PageFunction<T> desempeña un papel importante en la devolución de datos de PageFunction<T> a la página que la llama.

Llamar a pageFunction y pasar parámetros

Para llamar a una página, la página que realiza la llamada debe crear una instancia de la página llamada y navegar a ella mediante el Navigate método . Esto permite que la página de llamada pase los datos iniciales a la página llamada, como los valores predeterminados de los datos que recopila la página llamada.

El código siguiente muestra la página llamada con un constructor sin parámetros para aceptar parámetros de la página que llama.

using System;
using System.Windows;
using System.Windows.Navigation;

namespace StructuredNavigationSample
{
    public partial class CalledPageFunction : PageFunction<String>
    {
Imports System.Windows
Imports System.Windows.Navigation

Namespace StructuredNavigationSample

Public Class CalledPageFunction
    Inherits PageFunction(Of String)
public CalledPageFunction(string initialDataItem1Value)
{
    InitializeComponent();

Public Sub New(ByVal initialDataItem1Value As String)
    Me.InitializeComponent()
    // Set initial value
    this.dataItem1TextBox.Text = initialDataItem1Value;
}
    ' Set initial value
    Me.dataItem1TextBox.Text = initialDataItem1Value
End Sub
    }
}
End Class

End Namespace

El siguiente código muestra la página que llama, la cual maneja el evento Click del Hyperlink para instanciar la página llamada y pasarle un valor de cadena inicial.

<Hyperlink Name="pageFunctionHyperlink">Call Page Function</Hyperlink>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace StructuredNavigationSample
{
    public partial class CallingPage : Page
    {
        public CallingPage()
        {
            InitializeComponent();
            this.pageFunctionHyperlink.Click += new RoutedEventHandler(pageFunctionHyperlink_Click);
        }
        void pageFunctionHyperlink_Click(object sender, RoutedEventArgs e)
        {

            // Instantiate and navigate to page function
            CalledPageFunction CalledPageFunction = new CalledPageFunction("Initial Data Item Value");
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Navigation

Namespace StructuredNavigationSample

Public Class CallingPage
    Inherits Page
    Public Sub New()
        Me.InitializeComponent()
        AddHandler Me.pageFunctionHyperlink.Click, New RoutedEventHandler(AddressOf Me.pageFunctionHyperlink_Click)
    End Sub
    Private Sub pageFunctionHyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
}
End Sub
    }
}
End Class

End Namespace

No es necesario pasar parámetros a la página llamada. En su lugar, puede hacer lo siguiente:

Pero, como verá en breve, necesitará usar código para crear instancias y navegar a la página llamada para recopilar los datos devueltos por la página llamada. Por este motivo, debe PageFunction<T> mantenerse activo; de lo contrario, la próxima vez que vaya a PageFunction<T>, WPF crea una instancia del PageFunction<T> mediante el constructor sin parámetros.

Sin embargo, antes de que la página llamada pueda devolver, necesita devolver datos que la página de llamada pueda recuperar.

Devolver el resultado de la tarea y los datos de una tarea a la página que la llama

Una vez que el usuario haya terminado de usar la página llamada, lo cual se indica en este ejemplo presionando los botones Aceptar o Cancelar, la página llamada debe volver. Dado que la página de llamada usó la página llamada para recopilar datos del usuario, la página de llamada requiere dos tipos de información:

  1. Si el usuario canceló la página llamada (presionando el botón Aceptar o el botón Cancelar en este ejemplo). Esto permite que la página de llamada determine si se procesan los datos recopilados por el usuario en la página que realiza la llamada.

  2. Los datos proporcionados por el usuario.

Para devolver información, PageFunction<T> implementa el OnReturn método . En el código siguiente se muestra cómo llamarlo.

using System;
using System.Windows;
using System.Windows.Navigation;

namespace StructuredNavigationSample
{
    public partial class CalledPageFunction : PageFunction<String>
    {
Imports System.Windows
Imports System.Windows.Navigation

Namespace StructuredNavigationSample

Public Class CalledPageFunction
    Inherits PageFunction(Of 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);
        }
    }
}
    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

En este ejemplo, si un usuario presiona el botón Cancelar, se devuelve un valor de null a la página que realiza la llamada. Si se presiona el botón Aceptar en su lugar, se devuelve el valor de cadena proporcionado por el usuario. OnReturn es un protected virtual método al que se llama para devolver los datos a la página que realiza la llamada. Los datos deben empaquetarse en una instancia del tipo genérico ReturnEventArgs<T> , cuyo argumento type especifica el tipo de valor que Result devuelve. De este modo, cuando se declara con PageFunction<T> un argumento de tipo determinado, se indica que un PageFunction<T> devolverá una instancia del tipo especificado por el argumento type. En este ejemplo, el argumento type y, en consecuencia, el valor devuelto es de tipo String.

Cuando se llama a OnReturn, la página que realiza la llamada necesita una manera de recibir el valor de retorno de PageFunction<T>. Por este motivo, PageFunction<T> implementa el evento Return para que las páginas lo gestionen. Cuando se llama a OnReturn, se genera Return, por lo que la página que realiza la llamada puede registrarse con Return para recibir la notificación.

using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace StructuredNavigationSample
{
    public partial class CallingPage : Page
    {
Imports System.Windows
Imports System.Windows.Controls
Imports System.Windows.Navigation

Namespace StructuredNavigationSample

Public Class CallingPage
    Inherits 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;
            }
        }
    }
}
    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

Quitar páginas de tareas cuando se completa una tarea

Cuando una página llamada vuelve y el usuario no ha cancelado la página llamada, la página que realiza la llamada procesará los datos proporcionados por el usuario y también devueltos por la página llamada. La adquisición de datos de esta manera suele ser una actividad aislada; cuando se devuelve la página llamada, la página que realiza la llamada debe crear una nueva página de llamada y navegar a ella para capturar más datos.

Sin embargo, a menos que se quite una página llamada del diario, un usuario podrá volver a una instancia anterior de la página que realiza la llamada. La propiedad PageFunction<T> determina si un RemoveFromJournal se conserva en el diario. De forma predeterminada, una función de página se elimina 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 que se llame a OnReturn, establezca RemoveFromJournal a false.

Otros tipos de navegación estructurada

En este tema se ilustra el uso más básico de un PageFunction<T> para soportar la navegación estructurada de retorno y llamada. Esta base le proporciona la capacidad de crear tipos más complejos de navegación estructurada.

Por ejemplo, a veces se requieren varias páginas mediante una página de llamada para recopilar suficientes datos de un usuario o para realizar una tarea. El uso de varias páginas se conoce como "asistente".

En otros casos, las aplicaciones pueden tener topologías de navegación complejas que dependen de la navegación estructurada para funcionar de forma eficaz. Para obtener más información, consulte Introducción a las topologías de navegación.

Consulte también