Visão geral da navegação estruturada
O conteúdo que pode ser hospedado por um aplicativo de navegador XAML (XBAP), um Frameou um NavigationWindow é composto por páginas que podem ser identificadas por URIs (uniform resource identifiers) de pacote e navegadas por hiperlinks. A estrutura das páginas e as formas como podem ser navegadas, conforme definido por hiperligações, é conhecida como topologia de navegação. Essa topologia se adequa a uma variedade de tipos de aplicativos, particularmente aqueles que navegam pelos documentos. Para tais aplicações, o usuário pode navegar de uma página para outra página sem que nenhuma página precise saber nada sobre a outra.
No entanto, outros tipos de aplicativos têm páginas que precisam saber quando foram navegadas entre elas. Por exemplo, considere um aplicativo de recursos humanos que tenha uma página para listar todos os funcionários de uma organização — a página "Listar funcionários". Esta página também pode permitir que os usuários adicionem um novo funcionário clicando em um hiperlink. Quando clicada, a página navega até uma página "Adicionar um funcionário" para reunir os detalhes do novo funcionário e devolvê-los à página "Listar funcionários" para criar o novo funcionário e atualizar a lista. Esse estilo de navegação é semelhante a chamar um método para executar algum processamento e retornar um valor, que é conhecido como programação estruturada. Como tal, este estilo de navegação é conhecido como navegação estruturada.
A classe Page não implementa suporte para navegação estruturada. Em vez disso, a classe PageFunction<T> deriva de Page e a estende com as construções básicas necessárias para a navegação estruturada. Este tópico mostra como estabelecer navegação estruturada usando PageFunction<T>.
Navegação estruturada
Quando uma página chama outra página em uma navegação estruturada, alguns ou todos os seguintes comportamentos são necessários:
A página de chamada navega até a página chamada, opcionalmente passando os parâmetros exigidos pela página chamada.
A página chamada, quando um usuário conclui usando a página de chamada, retorna especificamente para a página de chamada, opcionalmente:
Retornando informações de estado que descrevem como a página de chamada foi concluída (por exemplo, se um usuário pressionou um botão OK ou um botão Cancelar).
Retornar os dados que foram coletados do usuário (por exemplo, detalhes de novos funcionários).
Quando a página de chamada retorna à página chamada, a página chamada é removida do histórico de navegação para isolar uma instância de uma página chamada de outra.
Estes comportamentos são ilustrados pela seguinte figura:
Você pode implementar esses comportamentos usando um PageFunction<T> como a página chamada.
Navegação estruturada com PageFunction
Este tópico mostra como implementar a mecânica básica da navegação estruturada envolvendo um único PageFunction<T>. Neste exemplo, um Page chama um PageFunction<T> para obter do utilizador um valor String e devolvê-lo.
Criando uma página de chamada
A página que chama um PageFunction<T> pode ser um Page ou um PageFunction<T>. Neste exemplo, é um Page, conforme mostrado no código a seguir.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="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
Criar uma função de página que será chamada
Como a página de chamada pode usar a página chamada para coletar e retornar dados do usuário, PageFunction<T> é implementada como uma classe genérica cujo argumento type especifica o tipo do valor que a página chamada retornará. O código a seguir mostra a implementação inicial da página chamada, usando um PageFunction<T>, que retorna um 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
A declaração de um PageFunction<T> é semelhante à declaração de um Page com a adição dos argumentos type. Como se pode ver no exemplo de código, os argumentos de tipo são indicados tanto na marcação XAML, usando o atributo x:TypeArguments
, como no code-behind, usando a sintaxe genérica padrão do argumento de tipo.
Você não precisa usar apenas classes do .NET Framework como argumentos de tipo. Um PageFunction<T> pode ser chamado para coletar dados específicos do domínio que são abstraídos como um tipo personalizado. O código a seguir mostra como usar um tipo personalizado como um argumento de tipo para um 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
Os argumentos de tipo para o PageFunction<T> fornecem a base para a comunicação entre a página que faz a chamada e a página que foi chamada, as quais são discutidas nas seguintes seções.
Como você verá, o tipo identificado com a declaração de um PageFunction<T> desempenha um papel importante no retorno de dados de um PageFunction<T> para a página de chamada.
Chamando uma PageFunction e passando parâmetros
Para chamar uma página, a página de chamada deve instanciar a página chamada e navegar até ela usando o método Navigate. Isso permite que a página de chamada passe dados iniciais para a página chamada, como valores padrão para os dados que estão sendo coletados pela página chamada.
O código a seguir mostra a página chamada com um construtor sem parâmetros para aceitar parâmetros da página de chamada.
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
O código a seguir mostra a página de chamada manipulando o evento Click do Hyperlink para instanciar a página chamada e passar um valor de cadeia de caracteres 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
Não é necessário passar parâmetros para a página chamada. Em vez disso, você pode fazer o seguinte:
Na página de chamada:
Instancie o chamado PageFunction<T> usando o construtor sem parâmetros.
Armazene os parâmetros em Properties.
Navegue até ao chamado PageFunction<T>.
Do elemento chamado PageFunction<T>:
- Recupere e use os parâmetros armazenados em Properties.
Mas, como você verá em breve, você ainda precisará usar o código para instanciar e navegar até a página chamada para coletar os dados retornados pela página chamada. Por esta razão, o PageFunction<T> precisa ser mantido vivo; caso contrário, da próxima vez que você navegar para o PageFunction<T>, o WPF instanciará o PageFunction<T> usando o construtor sem parâmetros.
Antes que a página chamada possa retornar, no entanto, ela precisa retornar dados que podem ser recuperados pela página de chamada.
Retornar o resultado e os dados de uma tarefa para uma página chamadora
Quando o usuário terminar de usar a página chamada, representada neste exemplo pressionando os botões OK ou Cancelar, a página chamada precisa retornar. Como a página de chamada usava a página chamada para coletar dados do usuário, a página de chamada requer dois tipos de informações:
Se o usuário cancelou a página chamada (pressionando o botão OK ou o botão Cancelar neste exemplo). Isso permite que a página de chamada determine se deve processar os dados que a página de chamada coletou do usuário.
Os dados que foram fornecidos pelo usuário.
Para retornar informações, PageFunction<T> implementa o método OnReturn. O código a seguir mostra como chamá-lo.
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
Neste exemplo, se um usuário pressionar o botão Cancelar, um valor de null
será retornado para a página de chamada. Se o botão OK for pressionado, o valor da cadeia de caracteres fornecido pelo usuário será retornado.
OnReturn é um método protected virtual
que você chama para retornar seus dados para a página de chamada. Seus dados precisam ser empacotados em uma instância do tipo ReturnEventArgs<T> genérico, cujo argumento type especifica o tipo de valor que Result retorna. Dessa forma, quando você declara um PageFunction<T> com um argumento de tipo específico, você está afirmando que um PageFunction<T> retornará uma instância do tipo especificado pelo argumento type. Neste exemplo, o argumento type e, consequentemente, o valor de retorno é do tipo String.
Quando OnReturn é chamado, a página de chamada precisa de alguma forma de receber o valor de retorno do PageFunction<T>. Por esse motivo, PageFunction<T> implementa o evento Return para que as páginas de chamada possam manipular. Quando OnReturn é chamado, Return é acionado, para que a página que chama possa registar-se com Return para receber a notificação.
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
Removendo páginas de tarefas quando uma tarefa é concluída
Quando uma página chamada retorna e o usuário não cancelou a página chamada, a página de chamada processará os dados que foram fornecidos pelo usuário e também retornaram da página chamada. A aquisição de dados desta forma é geralmente uma atividade isolada; Quando a página chamada retorna, a página de chamada precisa criar e navegar até uma nova página de chamada para capturar mais dados.
No entanto, a menos que uma página chamada seja removida do diário, um usuário poderá navegar de volta para uma instância anterior da página de chamada. A retenção de um PageFunction<T> no diário é determinada pela propriedade RemoveFromJournal. Por padrão, uma função de página é removida automaticamente quando OnReturn é chamada porque RemoveFromJournal está definida como true
. Para manter uma função de página no histórico de navegação após OnReturn ser chamada, defina RemoveFromJournal como false
.
Outros tipos de navegação estruturada
Este tópico ilustra o uso mais básico de um PageFunction<T> para dar suporte à navegação estruturada de chamada/retorno. Essa base fornece a capacidade de criar tipos mais complexos de navegação estruturada.
Por exemplo, às vezes várias páginas são necessárias para uma página de chamada para coletar dados suficientes de um usuário ou para executar uma tarefa. O uso de várias páginas é usualmente referido como um "assistente".
Em outros casos, os aplicativos podem ter topologias de navegação complexas que dependem da navegação estruturada para operar de forma eficaz. Para obter mais informações, consulte Visão geral de topologias de navegação .
Ver também
- PageFunction<T>
- NavigationService
- Visão geral de topologias de navegação
.NET Desktop feedback