Condividi tramite


Panoramica sulla Navigazione Strutturata

Il contenuto che può essere ospitato da un'applicazione browser XAML (XBAP), un Frameo un NavigationWindow è costituito da pagine che possono essere identificate da URI (Uniform Resource Identifier) e raggiunte tramite collegamenti ipertestuali. La struttura delle pagine e i modi in cui è possibile spostarsi, come definito dai collegamenti ipertestuali, è nota come topologia di navigazione. Tale topologia si adatta a un'ampia gamma di tipi di applicazione, in particolare quelli che si spostano tra i documenti. Per tali applicazioni, l'utente può spostarsi da una pagina a un'altra senza dover sapere nulla sull'altro.

Tuttavia, altri tipi di applicazioni hanno pagine che hanno bisogno di sapere quando si è navigato tra di esse. Si consideri, ad esempio, un'applicazione di risorse umane con una pagina per elencare tutti i dipendenti di un'organizzazione, ovvero la pagina "Elenca dipendenti". Questa pagina può anche consentire agli utenti di aggiungere un nuovo dipendente facendo clic su un collegamento ipertestuale. Quando si fa clic, la pagina passa a una pagina "Aggiungi un dipendente" per raccogliere i dettagli del nuovo dipendente e restituirli alla pagina "Elenca dipendenti" per creare il nuovo dipendente e aggiornare l'elenco. Questo stile di navigazione è simile alla chiamata di un metodo per eseguire alcune elaborazioni e restituire un valore, noto come programmazione strutturata. Di conseguenza, questo stile di navigazione è noto come navigazione strutturata.

La classe Page non implementa il supporto per lo spostamento strutturato. Al contrario, la classe PageFunction<T> deriva da Page e la estende con i costrutti di base necessari per la navigazione strutturata. Questo argomento illustra come stabilire una navigazione strutturata tramite PageFunction<T>.

Navigazione Strutturata

Quando una pagina chiama un'altra pagina in uno spostamento strutturato, sono necessari alcuni o tutti i comportamenti seguenti:

  • La pagina chiamante passa alla pagina chiamata, passando facoltativamente i parametri richiesti dalla pagina chiamata.

  • La pagina di destinazione, quando un utente ha finito di utilizzare la pagina di origine, ritorna alla pagina di origine, se necessario:

    • Restituzione di informazioni sullo stato che descrivono come è stata completata la pagina chiamante, ad esempio se un utente ha premuto un pulsante OK o un pulsante Annulla.

    • Restituzione di tali dati raccolti dall'utente (ad esempio, nuovi dettagli dei dipendenti).

  • Quando la pagina chiamante torna alla pagina chiamata, la pagina chiamata viene rimossa dalla cronologia di navigazione per isolare un'istanza di una pagina chiamata da un'altra.

Questi comportamenti sono illustrati nella figura seguente:

Screenshot mostra il flusso tra pagina chiamante e pagina chiamata.

È possibile implementare questi comportamenti usando un PageFunction<T> come pagina chiamata.

Strutturata navigazione con PageFunction

In questo argomento viene illustrato come implementare i meccanismi di base di navigazione strutturata che coinvolgono un singolo PageFunction<T>. In questo esempio un Page chiama un PageFunction<T> per ottenere un valore String dall'utente e restituirlo.

Creazione di una pagina di chiamata

La pagina che chiama un PageFunction<T> può essere un Page o un PageFunction<T>. In questo esempio si tratta di un Page, come illustrato nel codice seguente.

<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

Creazione di una funzione di pagina da chiamare

Poiché la pagina chiamante può utilizzare la pagina chiamata per raccogliere e restituire dati dall'utente, PageFunction<T> viene implementata come classe generica il cui argomento di tipo specifica il tipo del valore restituito dalla pagina chiamata. Il codice seguente illustra l'implementazione iniziale della pagina chiamata, usando un PageFunction<T>, che restituisce 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 dichiarazione di un PageFunction<T> è simile alla dichiarazione di un Page con l'aggiunta degli argomenti di tipo. Come puoi vedere dall'esempio di codice, gli argomenti di tipo vengono specificati sia nel markup XAML, usando l’attributo x:TypeArguments, sia nel file code-behind, usando la sintassi standard degli argomenti di tipo generico.

Non è necessario usare solo le classi .NET Framework come argomenti di tipo. È possibile effettuare una chiamata a un PageFunction<T> per raccogliere dati specifici del dominio, astratti come tipo personalizzato. Nel codice seguente viene illustrato come usare un tipo personalizzato come argomento di tipo per un 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

Gli argomenti di tipo per il PageFunction<T> forniscono le basi per la comunicazione tra una pagina chiamante e la pagina chiamata, descritte nelle sezioni seguenti.

Come vedrai, il tipo identificato con la dichiarazione di un PageFunction<T> svolge un ruolo importante nel trasferimento di dati da un PageFunction<T> alla pagina chiamante.

Chiamare una PageFunction e passare parametri

Per chiamare una pagina, la pagina chiamante deve creare un'istanza della pagina chiamata e navigare verso di essa usando il metodo Navigate. Ciò consente alla pagina chiamante di passare i dati iniziali alla pagina chiamata, ad esempio i valori predefiniti per i dati raccolti dalla pagina chiamata.

Il codice seguente mostra la pagina chiamata con un costruttore senza parametri per accettare i parametri dalla pagina chiamante.

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

Nel codice seguente viene illustrata la pagina chiamante che gestisce l'evento Click del Hyperlink per istanziare la pagina chiamata e passarle un valore iniziale di tipo stringa.

<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

Non è necessario passare parametri alla pagina chiamata. È invece possibile eseguire le operazioni seguenti:

Tuttavia, come si vedrà a breve, sarà comunque necessario usare il codice per creare un'istanza e passare alla pagina chiamata per raccogliere i dati restituiti dalla pagina chiamata. Per questo motivo, il PageFunction<T> deve essere mantenuto attivo; in caso contrario, la volta successiva che si naviga alla PageFunction<T>, WPF crea un'istanza del PageFunction<T> usando il costruttore senza parametri.

Prima che la pagina chiamata possa restituire, tuttavia, deve restituire i dati che possono essere recuperati dalla pagina chiamante.

Restituzione del risultato e dei dati di un'attività a una pagina chiamante

Al termine dell'utilizzo della pagina chiamata, indicato in questo esempio premendo i pulsanti OK o Annulla, la pagina chiamata deve tornare. Poiché la pagina chiamante ha usato la pagina chiamata per raccogliere dati dall'utente, la pagina chiamante richiede due tipi di informazioni:

  1. Indica se l'utente ha annullato la pagina chiamata (premendo il pulsante OK o il pulsante Annulla in questo esempio). Ciò consente alla pagina chiamante di determinare se elaborare i dati raccolti dall'utente dalla pagina chiamante.

  2. Dati forniti dall'utente.

Per restituire informazioni, PageFunction<T> implementa il metodo OnReturn. Il codice seguente illustra come chiamarlo.

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

In questo esempio, se un utente preme il pulsante Annulla, viene restituito un valore di null alla pagina chiamante. Se invece viene premuto il pulsante OK, viene restituito il valore stringa fornito dall'utente. OnReturn è un metodo protected virtual chiamato per restituire i dati alla pagina chiamante. I tuoi dati devono essere inseriti in un'istanza del tipo generico ReturnEventArgs<T>, il cui argomento specifica il tipo di valore che Result restituisce. In questo modo, quando si dichiara un PageFunction<T> con un argomento di tipo specifico, si indica che un 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 è di tipo String.

Quando viene chiamato OnReturn, la pagina chiamante richiede un modo per ricevere il valore restituito del PageFunction<T>. Per questo motivo, PageFunction<T> implementa l'evento Return per chiamare le pagine da gestire. Quando viene chiamato OnReturn, viene generato Return, in modo che la pagina chiamante possa registrarsi con Return per ricevere la notifica.

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

Rimozione delle pagine delle attività al termine di un'attività

Quando una pagina chiamata viene restituita e l'utente non ha annullato la pagina chiamata, la pagina chiamante elabora i dati forniti dall'utente e anche i dati restituiti dalla pagina chiamata. L'acquisizione dei dati in questo modo è in genere un'attività isolata; quando la pagina chiamata viene restituita, la pagina chiamante deve creare e passare a una nuova pagina di chiamata per acquisire più dati.

Tuttavia, a meno che una pagina chiamata non venga rimossa dal registro, un utente potrà tornare a un'istanza precedente della pagina chiamante. Se un PageFunction<T> viene conservato nel journal è determinato dalla proprietà RemoveFromJournal. Per impostazione predefinita, una funzione di pagina viene rimossa automaticamente quando viene chiamato OnReturn perché RemoveFromJournal è impostato su true. Per mantenere una funzione di pagina nella cronologia di navigazione dopo la chiamata di OnReturn, impostare RemoveFromJournal su false.

Altri tipi di navigazione strutturata

In questo argomento viene illustrato l'uso più semplice di un PageFunction<T> per sostenere la navigazione strutturata di chiamata e ritorno. Questa base offre la possibilità di creare tipi più complessi di navigazione strutturata.

Ad esempio, a volte più pagine sono richieste da una pagina chiamante per raccogliere dati sufficienti da un utente o per eseguire un'attività. L'uso di più pagine viene definito "procedura guidata".

In altri casi, le applicazioni possono avere topologie di navigazione complesse che dipendono dall'esplorazione strutturata per operare in modo efficace. Per ulteriori informazioni, consultare Panoramica delle topologie di spostamento.

Vedere anche