Cenni preliminari sulla navigazione strutturata
Il contenuto che può essere ospitato da un'XAML browser application (XBAP), un oggetto Frameo un oggetto NavigationWindow è composto da pagine che è possibile identificare tramite gli uniform resource identifiers (URIs) di tipo pack ed essere esplorate mediante collegamenti ipertestuali. La struttura delle pagine e le modalità di spostamento, definite dai collegamenti ipertestuali, sono note come topologia di spostamento. Tale topologia si adatta a vari tipi di applicazione, in particolare alle applicazioni che si spostano tra documenti. Per tali applicazioni, l'utente può spostarsi da una pagina a un'altra, senza che tali pagine siano a conoscenza l'una dell'altra.
In altri tipi di applicazioni, tuttavia, è necessario tenere traccia degli spostamenti tra le pagine. Si consideri, ad esempio, un'applicazione delle risorse umane con una pagina in cui sono elencati tutti i dipendenti di un'organizzazione, la pagina "Elenco dipendenti". In questa pagina è anche possibile aggiungere un nuovo dipendente facendo clic su un collegamento ipertestuale. Quando si fa clic nella pagina, viene visualizzata la pagina "Aggiungi dipendente" in cui vengono raccolte le informazioni sul nuovo dipendente, restituite quindi alla pagina "Elenco dipendenti" per creare il nuovo dipendente e aggiornare l'elenco. Questo stile di spostamento è simile alla chiamata a un metodo affinché venga eseguita un'elaborazione e venga restituito un valore, operazione nota come programmazione strutturata. Analogamente, questo stile di spostamento è noto come spostamento strutturato.
La classe Page non implementa il supporto per lo spostamento strutturato. La classe PageFunction<T> deriva invece da Page e lo estende con i costrutti di base richiesti per lo spostamento strutturato. In questo argomento viene illustrato come definire lo spostamento strutturato con PageFunction<T>.
Nel presente argomento sono contenute le seguenti sezioni.
- Spostamento strutturato
- Spostamento strutturato con PageFunction
- Altri tipi di spostamento strutturato
- Argomenti correlati
Spostamento strutturato
Quando una pagina chiama un'altra pagina nello spostamento strutturato, sono richiesti alcuni dei comportamenti riportati di seguito, o tutti:
La pagina chiamante si sposta nella pagina chiamata, passando facoltativamente i parametri richiesti dalla pagina chiamata.
La pagina chiamata, al completamento dell'utilizzo della pagina chiamante, torna specificamente alla pagina chiamante e, facoltativamente, vengono eseguite le operazioni seguenti:
Vengono restituite informazioni sullo stato che descrivono la modalità di completamento della pagina chiamante (ad esempio, se si fa clic su un pulsante OK o Annulla).
Vengono restituiti i dati raccolti dall'utente (ad esempio, i dettagli sul nuovo dipendente).
Quando la pagina chiamante torna alla pagina chiamata, quest'ultima viene rimossa dalla cronologia di spostamento per isolare un'istanza di una pagina chiamata da un'altra.
Questi comportamenti sono illustrati nella figura riportata di seguito.
È possibile implementare questi comportamenti utilizzando PageFunction<T> come pagina chiamata.
Spostamento strutturato con PageFunction
In questo argomento viene illustrato come implementare il funzionamento di base dello spostamento strutturato che prevede un solo oggetto PageFunction<T>. In questo esempio, Page chiama PageFunction<T> per ottenere un valore String dall'utente e restituirlo.
Creazione di una pagina chiamante
La pagina che chiama PageFunction<T> può essere Page o PageFunction<T>. In questo esempio, viene utilizzato Page, come illustrato nel codice seguente.
<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();
...
}
...
}
}
Creazione di una funzione di pagina da chiamare
Affinché la pagina chiamante possa utilizzare la pagina chiamata per raccogliere dati dall'utente e restituirli, viene implementato PageFunction<T> come classe generica il cui argomento di tipo specifica il tipo di valore restituito dalla pagina chiamata. Nel codice riportato di seguito viene illustrata l'implementazione iniziale della pagina chiamata, mediante PageFunction<T> che restituisce 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 dichiarazione di PageFunction<T> è simile alla dichiarazione di Page con l'aggiunta degli argomenti di tipo. Come si nota dall'esempio di codice, gli argomenti di tipo sono specificati sia nel markup XAML, che utilizza l'attributo x:TypeArguments, sia nel code-behind, che utilizza la sintassi degli argomenti di tipo generico standard.
Non è necessario utilizzare solo le classi .NET Framework come argomenti di tipo. È possibile chiamare PageFunction<T> per raccogliere dati specifici del dominio estratti come tipo personalizzato. Nel codice riportato di seguito viene illustrato come utilizzare un tipo personalizzato come argomento di tipo per PageFunction<T>.
Public Class CustomType
...
End Class
namespace SDKSample
{
public class CustomType
{
...
}
}
<PageFunction
xmlns="https://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="https://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:SDKSample"
x:Class="SDKSample.CustomTypePageFunction"
x:TypeArguments="local:CustomType">
...
</PageFunction>
Partial Public Class CustomTypePageFunction
Inherits System.Windows.Navigation.PageFunction(Of CustomType)
using System.Windows.Navigation; // PageFunction
namespace SDKSample
{
public partial class CustomTypePageFunction : PageFunction<CustomType>
{
Gli argomenti di tipo per PageFunction<T> forniscono le basi per la comunicazione tra una pagina chiamante e la pagina chiamata, illustrate nelle sezioni che seguono.
Come verrà illustrato, il tipo identificato con la dichiarazione di PageFunction<T> riveste un ruolo importante nel restituire dati da PageFunction<T> alla pagina chiamante.
Chiamata di PageFunction e passaggio di parametri
Per chiamare una pagina, è necessario che nella pagina chiamante venga creata un'istanza della pagina chiamata, in cui effettuare lo spostamento tramite il metodo Navigate. In questo modo, è possibile passare i dati iniziali dalla pagina chiamante alla pagina chiamata, ad esempio i valori predefiniti dei dati raccolti dalla pagina chiamata.
Nel codice riportato di seguito viene illustrata la pagina chiamata con un costruttore non predefinito per accettare parametri dalla pagina chiamante.
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;
}
...
}
}
Nel codice riportato di seguito viene illustrata la pagina chiamante in cui viene gestito l'evento Click di Hyperlink dichiarato in precedenza, per creare un'istanza della pagina chiamata e passarvi un valore di stringa iniziale.
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()
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
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();
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");
...
}
...
}
}
<Hyperlink Name="pageFunctionHyperlink">Call Page Function</Hyperlink>
Non è necessario passare parametri alla pagina chiamata. È invece possibile effettuare le operazioni seguenti:
Dalla pagina chiamante:
Creare un'istanza dell'oggetto PageFunction<T> chiamato, utilizzando il costruttore predefinito.
Archiviare i parametri in Properties.
Spostarsi nell'oggetto PageFunction<T> chiamato.
Dall'oggetto PageFunction<T> chiamato:
- Recuperare e utilizzare i parametri archiviati in Properties.
Come verrà illustrato successivamente, è ancora necessario utilizzare codice per creare un'istanza e spostarsi nella pagina chiamata per raccogliere i dati restituiti dalla pagina chiamata. Per questo motivo, è necessario mantenere attivo PageFunction<T>, in caso contrario al successivo spostamento in PageFunction<T>, in WPF verrà creata un'istanza di PageFunction<T> utilizzando il costruttore predefinito.
Prima della restituzione della pagina chiamata, tuttavia, è necessario che tale pagina restituisca i dati che possono essere recuperati dalla pagina chiamante.
Restituzione del risultato e dei dati di attività da un'attività a una pagina chiamante
Al termine dell'utilizzo della pagina chiamata, indicato in questo esempio dalla scelta dei pulsanti OK o Annulla, la pagina chiamata deve essere restituita. Poiché la pagina chiamata è stata utilizzata dalla pagina chiamante per raccogliere dati dall'utente, la pagina chiamante richiede due tipi di informazioni:
L'utente ha annullato la pagina chiamata (scegliendo OK o Annulla in questo esempio). Grazie a questa informazione, la pagina chiamante è in grado di determinare se i dati raccolti dall'utente nella pagina chiamante devono essere elaborati.
I dati forniti dall'utente.
Per restituire informazioni, PageFunction<T> implementa il metodo OnReturn. Nel codice riportato di seguito viene illustrato come chiamare tale metodo.
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);
}
}
}
In questo esempio, se un utente fa clic su Annulla, un valore null viene restituito alla pagina chiamante. Se si sceglie invece il pulsante OK, viene restituito il valore della stringa fornito dall'utente. OnReturn è un metodo protected virtual chiamato per restituire i dati alla pagina chiamante. I dati devono essere assemblati in un'istanza del tipo ReturnEventArgs<T> generico il cui argomento di tipo specifica il tipo di valore restituito da Result. In questo modo, quando PageFunction<T> viene dichiarato con un determinato argomento di tipo, viene dichiarato che PageFunction<T> restituirà un'istanza del tipo specificato dall'argomento di tipo. In questo esempio, l'argomento di tipo e, di conseguenza, il valore restituito sono di tipo String.
Quando viene chiamato OnReturn, la pagina chiamante richiede un modo per ricevere il valore restituito di PageFunction<T>. Per questo motivo, PageFunction<T> implementa l'evento Return che verrà gestito dalle pagine chiamanti. Quando viene chiamato OnReturn, viene generato Return, in modo da consentire alla pagina chiamante la registrazione con Return per ricevere la notifica.
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;
}
}
}
}
Rimozione delle pagine di attività al completamento dell'attività
Quando viene restituita una pagina chiamata che non è stata annullata dall'utente, la pagina chiamante elabora i dati forniti dall'utente e restituiti dalla pagina chiamata. Questo tipo di acquisizione dei dati è in genere un'attività isolata. Quando la pagina chiamata viene restituita, è necessario che la pagina chiamante crei una nuova pagina chiamante in cui spostarsi per acquisire più dati.
Tuttavia, a meno che una pagina chiamata non venga rimossa dal journal, un utente potrà spostarsi di nuovo in un'istanza precedente della pagina chiamante. Il fatto che PageFunction<T> venga mantenuto nel journal è determinato dalla proprietà RemoveFromJournal. Per impostazione predefinita, una funzione di pagina viene automaticamente rimossa quando viene chiamato OnReturn, poiché RemoveFromJournal è impostato su true. Per mantenere una funzione di pagina nella cronologia di spostamento dopo la chiamat a OnReturn, impostare RemoveFromJournal su false.
Altri tipi di spostamento strutturato
In questo argomento viene illustrato l'utilizzo di base di PageFunction<T> per il supporto dello spostamento strutturato di tipo chiamata/restituzione. Da questa base è possibile creare tipi di spostamento strutturato più complessi.
Ad esempio, talvolta in una pagina chiamante sono richieste più pagine per raccogliere una quantità di dati sufficiente da un utente o per eseguire un'attività. L'utilizzo di più pagine è noto come "procedura guidata".
In altri casi, le applicazioni possono presentare topologie di spostamento complesse che dipendono dallo spostamento strutturato per funzionare in modo efficiente. Per ulteriori informazioni, vedere Cenni preliminari sulle topologie di navigazione.