Cenni preliminari sulla navigazione

Windows Presentation Foundation (WPF) supporta lo spostamento in stile browser che può essere usato in due tipi di applicazioni: applicazioni autonome e applicazioni browser XAML (XBAP). Per creare un pacchetto del contenuto per lo spostamento, WPF fornisce la Page classe . È possibile spostarsi da un Page oggetto a un altro in modo dichiarativo, usando un Hyperlinkoggetto o a livello di codice tramite .NavigationService WPF usa il journal per ricordare le pagine che sono state spostate da e per tornare indietro.

Page, Hyperlink, NavigationServicee il journal costituiscono il nucleo del supporto di spostamento offerto da WPF. Questa panoramica esplora in dettaglio queste funzionalità prima di coprire il supporto avanzato della navigazione che include lo spostamento a file XAML (Extensible Application Markup Language) separati, file HTML e oggetti.

Nota

In questo argomento il termine "browser" si riferisce solo ai browser che possono ospitare applicazioni WPF, che attualmente includono Microsoft Internet Explorer e Firefox. Se specifiche funzionalità WPF sono supportate solo da un browser specifico, viene fatto riferimento alla versione del browser.

In questo argomento viene fornita una panoramica delle funzionalità di spostamento principali in WPF. Queste funzionalità sono disponibili sia per le applicazioni autonome che per gli XBAP, anche se questo argomento li presenta nel contesto di un XBAP.

Nota

Questo argomento non illustra come compilare e distribuire XBAP. Per altre informazioni sugli XBAP, vedere Cenni preliminari sulle applicazioni browser XAML WPF.

In questa sezione vengono illustrati gli aspetti seguenti della navigazione:

Implementazione di una pagina

In WPF è possibile passare a diversi tipi di contenuto che includono oggetti .NET Framework, oggetti personalizzati, valori di enumerazione, controlli utente, file XAML e file HTML. Tuttavia, si scoprirà che il modo più comune e pratico per creare pacchetti di contenuto consiste nell'usare Page. Page Implementa inoltre funzionalità specifiche per la navigazione per migliorarne l'aspetto e semplificare lo sviluppo.

Usando Page, puoi implementare in modo dichiarativo una pagina navigabile di contenuto XAML usando markup come illustrato di seguito.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" />

Un Page oggetto implementato nel markup XAML ha Page come elemento radice e richiede la dichiarazione dello spazio dei nomi XML WPF. L'elemento Page contiene il contenuto che si desidera passare a e visualizzare. Per aggiungere contenuto, impostare l'elemento Page.Content proprietà, come illustrato nel markup seguente.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <Page.Content>
    <!-- Page Content -->
    Hello, Page!
  </Page.Content>
</Page>

Page.Content può contenere solo un elemento figlio; nell'esempio precedente, il contenuto è una singola stringa, "Hello, Page!" In pratica, in genere si userà un controllo di layout come elemento figlio (vedere Layout) per contenere e comporre il contenuto.

Gli elementi figlio di un Page elemento vengono considerati come il contenuto di un Page oggetto e, di conseguenza, non è necessario usare la dichiarazione esplicita Page.Content . Il markup seguente è l'equivalente dichiarativo dell'esempio precedente.

<Page xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <!-- Page Content -->
  Hello, Page!
</Page>

In questo caso, Page.Content viene impostato automaticamente con gli elementi figlio dell'elemento Page . Per altre informazioni, vedere Modello di contenuto WPF.

Un solo Page markup è utile per la visualizzazione del contenuto. Tuttavia, un Page può anche visualizzare controlli che consentono agli utenti di interagire con la pagina e può rispondere all'interazione dell'utente gestendo eventi e chiamando la logica dell'applicazione. Un oggetto interattivo Page viene implementato usando una combinazione di markup e code-behind, come illustrato nell'esempio seguente.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.HomePage">
  Hello, from the XBAP HomePage!
</Page>
using System.Windows.Controls;

namespace SDKSample
{
    public partial class HomePage : Page
    {
        public HomePage()
        {
            InitializeComponent();
        }
    }
}

Imports System.Windows.Controls

Namespace SDKSample
    Partial Public Class HomePage
        Inherits Page
        Public Sub New()
            InitializeComponent()
        End Sub
    End Class
End Namespace

Per consentire il funzionamento congiunto di un file di markup e di un file code-behind, è necessaria la configurazione seguente:

  • Nel markup l'elemento Page deve includere l'attributo x:Class. Quando l'applicazione viene compilata, l'esistenza di nel file di markup fa sì che il motore di x:Class compilazione Microsoft (MSBuild) crei una partial classe che deriva da Page e abbia il nome specificato dall'attributo x:Class . Ciò richiede l'aggiunta di una dichiarazione dello spazio dei nomi XML per lo schema XAML ( xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ). La classe generata partial implementa InitializeComponent, che viene chiamata per registrare gli eventi e impostare le proprietà implementate nel markup.

  • Nel code-behind la classe deve essere una classe partial con lo stesso nome specificato dall'attributo x:Class nel markup e deve derivare da Page. In questo modo il file code-behind può essere associato alla partial classe generata per il file di markup quando l'applicazione viene compilata (vedere Compilazione di un'applicazione WPF).

  • Nel code-behind la classe Page deve implementare un costruttore che chiama il metodo InitializeComponent. Il metodo InitializeComponent viene implementato dalla classe partial generata dal file di markup per registrare gli eventi e impostare le proprietà definite nel markup.

Nota

Quando si aggiunge un nuovo Page progetto usando Visual Studio, Page viene implementato usando sia markup che code-behind e include la configurazione necessaria per creare l'associazione tra il markup e i file code-behind, come descritto qui.

Dopo aver creato un Pageoggetto , è possibile passare a esso. Per specificare il primo Page passaggio di un'applicazione, è necessario configurare l'avvio Page.

Configurazione di una pagina iniziale

I file XBAP richiedono che una determinata quantità di infrastruttura dell'applicazione sia ospitata in un browser. In WPF la Application classe fa parte di una definizione dell'applicazione che stabilisce l'infrastruttura dell'applicazione necessaria (vedere Panoramica sulla gestione delle applicazioni).

Una definizione dell'applicazione viene in genere implementata usando markup e code-behind, con il file di markup configurato come elemento MSBuildApplicationDefinition . Di seguito è riportata una definizione di applicazione per un XBAP.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.App" />
using System.Windows;

namespace SDKSample
{
    public partial class App : Application { }
}

Imports System.Windows

Namespace SDKSample
    Partial Public Class App
        Inherits Application
    End Class
End Namespace

Un XBAP può usare la definizione dell'applicazione per specificare un oggetto start Page, ovvero l'oggetto Page caricato automaticamente all'avvio di XBAP. A tale scopo, impostare la StartupUri proprietà con l'URI (Uniform Resource Identifier) per l'oggetto desiderato Page.

Nota

Nella maggior parte dei casi, viene Page compilato o distribuito con un'applicazione. In questi casi, l'URI che identifica un Page è un URI di tipo pack, ovvero un URI conforme allo schema pack . Gli URI di tipo Pack vengono illustrati più avanti in URI pack in WPF. Per passare a contenuto specifico è anche possibile usare lo schema HTTP, illustrato più avanti.

È possibile impostare StartupUri in modo dichiarativo nel markup, come illustrato nell'esempio seguente.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.App"
    StartupUri="PageWithHyperlink.xaml" />

In questo esempio l'attributo StartupUri viene impostato con un URI pack relativo che identifica HomePage.xaml. All'avvio di XBAP, HomePage.xaml viene automaticamente spostato e visualizzato. Questa operazione è illustrata nella figura seguente, che mostra un XBAP avviato da un server Web.

XBAP page

Nota

Per altre informazioni sullo sviluppo e la distribuzione di XBAP, vedere Cenni preliminari sulle applicazioni browser XAML WPF e Distribuzione di un'applicazione WPF.

Configurazione del titolo, della larghezza e dell'altezza della finestra host

Una cosa che potresti aver notato dalla figura precedente è che il titolo del browser e del pannello di tabulazioni è l'URI per XBAP. Oltre a essere lungo, il titolo non è visivamente gradevole né informativo. Per questo motivo, Page consente di modificare il titolo impostando la WindowTitle proprietà . Inoltre, è possibile configurare rispettivamente la larghezza e l'altezza della finestra del browser impostando WindowWidth e WindowHeight.

WindowTitle, WindowWidthe WindowHeight possono essere impostati in modo dichiarativo nel markup, come illustrato nell'esempio seguente.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.HomePage"
    WindowTitle="Page Title"
    WindowWidth="500"
    WindowHeight="200">
  Hello, from the XBAP HomePage!
</Page>

Il risultato è illustrato nella figura seguente.

Window title, height, width

Un tipico XBAP comprende diverse pagine. Il modo più semplice per spostarsi da una pagina a un'altra consiste nell'usare un oggetto Hyperlink. È possibile aggiungere in modo dichiarativo un Hyperlink oggetto a Page usando l'elemento Hyperlink , illustrato nel markup seguente.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page With Hyperlink"
  WindowWidth="250"
  WindowHeight="250">
<Hyperlink NavigateUri="UriOfPageToNavigateTo.xaml">
  Navigate to Another Page
</Hyperlink>
</Page>

Un Hyperlink elemento richiede quanto segue:

  • URI pack dell'oggetto Page a cui passare, come specificato dall'attributo NavigateUri .

  • Contenuto che un utente può fare clic per avviare la navigazione, ad esempio testo e immagini (per il contenuto che l'elemento Hyperlink può contenere, vedere Hyperlink).

Nella figura seguente viene illustrato un XBAP con un Page oggetto con un oggetto Hyperlink.

Page with Hyperlink

Come previsto, facendo clic sull'oggetto Hyperlink XBAP si passa all'oggetto Page identificato dall'attributo NavigateUri . Inoltre, XBAP aggiunge una voce per l'elenco Pagine recenti Page in Internet Explorer. come illustrato nella figura seguente.

Back and Forward buttons

Oltre a supportare la navigazione da una Page all'altra, Hyperlink supporta anche lo spostamento tra frammenti.

Navigazione in un frammento

Lo spostamento tra frammenti è lo spostamento a un frammento di contenuto nell'oggetto corrente Page o in un altro Pageoggetto . In WPF, un frammento di contenuto è il contenuto contenuto da un elemento denominato. Un elemento denominato è un elemento con il relativo Name set di attributi. Il markup seguente mostra un elemento denominato TextBlock che contiene un frammento di contenuto.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    WindowTitle="Page With Fragments" >
<!-- Content Fragment called "Fragment1" -->
<TextBlock Name="Fragment1">
  Ea vel dignissim te aliquam facilisis ...
</TextBlock>
</Page>

Hyperlink Per passare a un frammento di contenuto, l'attributo NavigateUri deve includere quanto segue:

  • URI di con il frammento di Page contenuto a cui passare.

  • Un carattere "#".

  • Nome dell'elemento nell'oggetto Page che contiene il frammento di contenuto.

Un URI frammento ha il formato seguente.

URIPage#NomeElemento

Di seguito viene illustrato un esempio di un oggetto Hyperlink configurato per passare a un frammento di contenuto.

<Page
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page That Navigates To Fragment" >
<Hyperlink NavigateUri="PageWithFragments.xaml#Fragment1">
  Navigate To pack Fragment
</Hyperlink>
</Page>

Nota

In questa sezione viene descritta l'implementazione predefinita dello spostamento dei frammenti in WPF. WPF consente anche di implementare uno schema di spostamento dei frammenti personalizzato che, in parte, richiede la gestione dell'evento NavigationService.FragmentNavigation .

Importante

Puoi passare a frammenti in pagine XAML sciolte (file XAML solo markup con Page come elemento radice) solo se le pagine possono essere sfogliate tramite HTTP.

Tuttavia, una pagina XAML separata può passare ai propri frammenti.

Sebbene Hyperlink consenta a un utente di avviare lo spostamento a un particolare Page, il lavoro di individuazione e download della pagina viene eseguito dalla NavigationService classe . Essenzialmente, NavigationService offre la possibilità di elaborare una richiesta di navigazione per conto del codice client, ad esempio Hyperlink. Implementa inoltre NavigationService un supporto di livello superiore per tenere traccia e influenzare una richiesta di navigazione.

Quando si fa clic su un oggetto Hyperlink , WPF chiama NavigationService.Navigate per individuare e scaricare in Page corrispondenza dell'URI del pacchetto specificato. L'oggetto scaricato Page viene convertito in un albero di oggetti il cui oggetto radice è un'istanza dell'oggetto scaricato Page. Un riferimento all'oggetto radice Page viene archiviato nella NavigationService.Content proprietà . L'URI del pacchetto per il contenuto a cui è stato eseguito lo spostamento viene archiviato nella NavigationService.Source proprietà , mentre archivia NavigationService.CurrentSource l'URI di pacchetto per l'ultima pagina a cui è stato eseguito lo spostamento.

Nota

È possibile che un'applicazione WPF disponga di più di un oggetto attualmente attivo NavigationService. Per altre informazioni, vedere Host di navigazione più avanti in questo argomento.

Navigazione a livello di codice tramite il servizio di navigazione

Non è necessario sapere se NavigationService la navigazione viene implementata in modo dichiarativo nel markup usando Hyperlink, perché Hyperlink usa per conto dell'utente NavigationService . Ciò significa che, purché l'elemento padre diretto o indiretto di un Hyperlink oggetto sia un host di navigazione (vedere Host di spostamento), Hyperlink sarà in grado di trovare e usare il servizio di spostamento dell'host di spostamento per elaborare una richiesta di navigazione.

Tuttavia, esistono situazioni in cui è necessario usare NavigationService direttamente, tra cui quanto segue:

  • Quando è necessario creare un'istanza Page di usando un costruttore senza parametri.

  • Quando è necessario impostare le proprietà in Page prima di passarvi.

  • Quando l'oggetto Page a cui deve essere eseguito lo spostamento può essere determinato solo in fase di esecuzione.

In queste situazioni, è necessario scrivere codice per avviare lo spostamento a livello di codice chiamando il Navigate metodo dell'oggetto NavigationService . Ciò richiede il recupero di un riferimento a un oggetto NavigationService.

Ottenere un riferimento a NavigationService

Per motivi illustrati nella sezione Host di spostamento, un'applicazione WPF può avere più di un NavigationServiceoggetto . Questo significa che il codice necessita di un modo per trovare un NavigationServiceoggetto , che in genere è quello NavigationService che si è spostato all'oggetto corrente Page. È possibile ottenere un riferimento a un NavigationService oggetto chiamando il staticNavigationService.GetNavigationService metodo . Per ottenere l'oggetto NavigationService che è passato a un particolare Pageoggetto , passare un riferimento all'oggetto Page come argomento del GetNavigationService metodo . Nel codice seguente viene illustrato come ottenere per l'oggetto NavigationService corrente Page.

using System.Windows.Navigation;
// Get a reference to the NavigationService that navigated to this Page
NavigationService ns = NavigationService.GetNavigationService(this);
' Get a reference to the NavigationService that navigated to this Page
Dim ns As NavigationService = NavigationService.GetNavigationService(Me)

Come collegamento per trovare per NavigationService un Pageoggetto , Page implementa la NavigationService proprietà . come illustrato nell'esempio seguente.

using System.Windows.Navigation;
// Get a reference to the NavigationService that navigated to this Page
NavigationService ns = this.NavigationService;
' Get a reference to the NavigationService that navigated to this Page
Dim ns As NavigationService = Me.NavigationService

Nota

Un Page oggetto può ottenere un riferimento al relativo NavigationService solo quando Page genera l'evento Loaded .

Navigazione a livello di codice in un oggetto Page

Nell'esempio seguente viene illustrato come usare per NavigationService passare a livello di codice a un oggetto Page. La navigazione a livello di codice è necessaria perché l'oggetto Page a cui si sta spostando può essere creata un'istanza solo usando un singolo costruttore senza parametri. L'oggetto Page con il costruttore senza parametri è illustrato nel markup e nel codice seguenti.

<Page
    x:Class="SDKSample.PageWithNonDefaultConstructor"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="PageWithNonDefaultConstructor">
  
  <!-- Content goes here -->
  
</Page>
using System.Windows.Controls;

namespace SDKSample
{
    public partial class PageWithNonDefaultConstructor : Page
    {
        public PageWithNonDefaultConstructor(string message)
        {
            InitializeComponent();

            this.Content = message;
        }
    }
}

Namespace SDKSample
    Partial Public Class PageWithNonDefaultConstructor
        Inherits Page
        Public Sub New(ByVal message As String)
            InitializeComponent()

            Me.Content = message
        End Sub
    End Class
End Namespace

L'oggetto PagePage che passa a con il costruttore senza parametri è illustrato nel markup e nel codice seguenti.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.NSNavigationPage">

  <Hyperlink Click="hyperlink_Click">
    Navigate to Page with Non-Default Constructor
  </Hyperlink>

</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class NSNavigationPage : Page
    {
        public NSNavigationPage()
        {
            InitializeComponent();
        }

        void hyperlink_Click(object sender, RoutedEventArgs e)
        {
            // Instantiate the page to navigate to
            PageWithNonDefaultConstructor page = new PageWithNonDefaultConstructor("Hello!");

            // Navigate to the page, using the NavigationService
            this.NavigationService.Navigate(page);
        }
    }
}

Namespace SDKSample
    Partial Public Class NSNavigationPage
        Inherits Page
        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub hyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Instantiate the page to navigate to
            Dim page As New PageWithNonDefaultConstructor("Hello!")

            ' Navigate to the page, using the NavigationService
            Me.NavigationService.Navigate(page)
        End Sub
    End Class
End Namespace

Quando si fa clic su , la Hyperlink navigazione viene avviata creando un'istanza di Page per passare a usando il costruttore senza parametri e chiamando il NavigationService.NavigatePage metodo . Navigate accetta un riferimento all'oggetto a cui verrà spostato l'oggetto NavigationService anziché un URI di tipo pack.

Navigazione a livello di codice con un URI di tipo pack

Se è necessario costruire un URI pack a livello di codice (quando è possibile determinare solo l'URI pack in fase di esecuzione, ad esempio), è possibile usare il NavigationService.Navigate metodo . come illustrato nell'esempio seguente.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.NSUriNavigationPage">
  <Hyperlink Click="hyperlink_Click">Navigate to Page by Pack URI</Hyperlink>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class NSUriNavigationPage : Page
    {
        public NSUriNavigationPage()
        {
            InitializeComponent();
        }

        void hyperlink_Click(object sender, RoutedEventArgs e)
        {
            // Create a pack URI
            Uri uri = new Uri("AnotherPage.xaml", UriKind.Relative);

            // Get the navigation service that was used to
            // navigate to this page, and navigate to
            // AnotherPage.xaml
            this.NavigationService.Navigate(uri);
        }
    }
}

Namespace SDKSample
    Partial Public Class NSUriNavigationPage
        Inherits Page
        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub hyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Create a pack URI
            Dim uri As New Uri("AnotherPage.xaml", UriKind.Relative)

            ' Get the navigation service that was used to 
            ' navigate to this page, and navigate to 
            ' AnotherPage.xaml
            Me.NavigationService.Navigate(uri)
        End Sub
    End Class
End Namespace

Aggiornamento della pagina corrente

Un Page oggetto non viene scaricato se ha lo stesso URI pack dell'URI pack archiviato nella NavigationService.Source proprietà . Per forzare WPF a scaricare nuovamente la pagina corrente, è possibile chiamare il NavigationService.Refresh metodo , come illustrato nell'esempio seguente.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.NSRefreshNavigationPage">
 <Hyperlink Click="hyperlink_Click">Refresh this page</Hyperlink>
</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class NSRefreshNavigationPage : Page
    {

Namespace SDKSample
    Partial Public Class NSRefreshNavigationPage
        Inherits Page
        void hyperlink_Click(object sender, RoutedEventArgs e)
        {
            // Force WPF to download this page again
            this.NavigationService.Refresh();
        }
    }
}
        Private Sub hyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Force WPF to download this page again
            Me.NavigationService.Refresh()
        End Sub
    End Class
End Namespace

Come si è visto, esistono diversi modi per avviare una navigazione. Quando viene avviato lo spostamento e durante la navigazione è in corso, è possibile tenere traccia e influenzare la navigazione usando gli eventi seguenti implementati da NavigationService:

  • Navigating. Si verifica quando viene richiesta una nuova navigazione. Può essere usato per annullare la navigazione.

  • NavigationProgress. Si verifica periodicamente durante un download per fornire informazioni sullo stato dello spostamento.

  • Navigated. Si verifica quando la pagina è stata individuata e scaricata.

  • NavigationStopped. Si verifica quando la navigazione viene arrestata (chiamando StopLoading) o quando viene richiesta una nuova navigazione mentre è in corso una navigazione corrente.

  • NavigationFailed. Si verifica quando viene generato un errore durante la navigazione nel contenuto richiesto.

  • LoadCompleted. Si verifica quando il contenuto di destinazione della navigazione è stato caricato e analizzato ed è iniziata l'esecuzione del rendering.

  • FragmentNavigation. Si verifica quando inizia la navigazione in un frammento di contenuto, che avviene:

    • Immediatamente, se il frammento desiderato si trova nel contenuto corrente.

    • Una volta caricato il contenuto di origine, se il frammento desiderato si trova in un contenuto diverso.

Gli eventi di navigazione vengono generati nell'ordine illustrato nella figura seguente.

Page navigation flow chart

In generale, un Page non è preoccupato per questi eventi. È più probabile che un'applicazione sia interessata e, per questo motivo, questi eventi vengono generati anche dalla Application classe :

Ogni volta che NavigationService genera un evento, la Application classe genera l'evento corrispondente. Frame e NavigationWindow offrono gli stessi eventi per rilevare la navigazione all'interno dei rispettivi ambiti.

In alcuni casi, un Page oggetto potrebbe essere interessato a questi eventi. Ad esempio, un Page può gestire l'evento NavigationService.Navigating per determinare se annullare o meno lo spostamento da se stesso. come illustrato nell'esempio seguente.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.CancelNavigationPage">
  <Button Click="button_Click">Navigate to Another Page</Button>
</Page>
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class CancelNavigationPage : Page
    {
        public CancelNavigationPage()
        {
            InitializeComponent();

            // Can only access the NavigationService when the page has been loaded
            this.Loaded += new RoutedEventHandler(CancelNavigationPage_Loaded);
            this.Unloaded += new RoutedEventHandler(CancelNavigationPage_Unloaded);
        }

        void button_Click(object sender, RoutedEventArgs e)
        {
            // Force WPF to download this page again
            this.NavigationService.Navigate(new Uri("AnotherPage.xaml", UriKind.Relative));
        }

        void CancelNavigationPage_Loaded(object sender, RoutedEventArgs e)
        {
            this.NavigationService.Navigating += new NavigatingCancelEventHandler(NavigationService_Navigating);
        }

        void CancelNavigationPage_Unloaded(object sender, RoutedEventArgs e)
        {
            this.NavigationService.Navigating -= new NavigatingCancelEventHandler(NavigationService_Navigating);
        }

        void NavigationService_Navigating(object sender, NavigatingCancelEventArgs e)
        {
            // Does the user really want to navigate to another page?
            MessageBoxResult result;
            result = MessageBox.Show("Do you want to leave this page?", "Navigation Request", MessageBoxButton.YesNo);

            // If the user doesn't want to navigate away, cancel the navigation
            if (result == MessageBoxResult.No) e.Cancel = true;
        }
    }
}

Namespace SDKSample
    Partial Public Class CancelNavigationPage
        Inherits Page
        Public Sub New()
            InitializeComponent()

            ' Can only access the NavigationService when the page has been loaded
            AddHandler Loaded, AddressOf CancelNavigationPage_Loaded
            AddHandler Unloaded, AddressOf CancelNavigationPage_Unloaded
        End Sub

        Private Sub button_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            ' Force WPF to download this page again
            Me.NavigationService.Navigate(New Uri("AnotherPage.xaml", UriKind.Relative))
        End Sub

        Private Sub CancelNavigationPage_Loaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
            AddHandler NavigationService.Navigating, AddressOf NavigationService_Navigating
        End Sub

        Private Sub CancelNavigationPage_Unloaded(ByVal sender As Object, ByVal e As RoutedEventArgs)
            RemoveHandler NavigationService.Navigating, AddressOf NavigationService_Navigating
        End Sub

        Private Sub NavigationService_Navigating(ByVal sender As Object, ByVal e As NavigatingCancelEventArgs)
            ' Does the user really want to navigate to another page?
            Dim result As MessageBoxResult
            result = MessageBox.Show("Do you want to leave this page?", "Navigation Request", MessageBoxButton.YesNo)

            ' If the user doesn't want to navigate away, cancel the navigation
            If result = MessageBoxResult.No Then
                e.Cancel = True
            End If
        End Sub
    End Class
End Namespace

Se si registra un gestore con un evento di navigazione da un Pageoggetto , come nell'esempio precedente, è anche necessario annullare la registrazione del gestore eventi. In caso contrario, potrebbero verificarsi effetti collaterali rispetto al modo in cui la navigazione WPF ricorda Page lo spostamento usando il journal.

Memorizzazione della navigazione tramite journal

WPF usa due stack per ricordare le pagine da cui si è passati: uno stack indietro e uno stack in avanti. Quando si passa dall'oggetto corrente Page a un nuovo Page o in avanti a un oggetto esistente Page, l'oggetto corrente Page viene aggiunto allo stack back. Quando si passa dall'oggetto corrente Page all'oggetto precedente Page, l'oggetto corrente Page viene aggiunto allo stack di inoltro. Per fare riferimento allo stack indietro, allo stack avanti e alla funzionalità di gestione degli stack nel loro complesso, si usa il termine journal. Ogni elemento nello stack back e nello stack forward è un'istanza della JournalEntry classe e viene definito voce journal.

Concettualmente, il journal funziona allo stesso modo in cui i pulsanti Indietro e Avanti in Internet Explorer. illustrati nella figura seguente.

Back and Forward buttons

Per gli XBAP ospitati da Internet Explorer, WPF integra il journal nell'interfaccia utente di navigazione di Internet Explorer. In questo modo gli utenti possono spostarsi tra le pagine in un XBAP usando i pulsanti Indietro, Avanti e Pagine recenti in Internet Explorer.

Importante

In Internet Explorer, quando un utente si sposta da e torna a un XBAP, solo le voci del journal per le pagine non mantenute attive vengono conservate nel journal. Per informazioni su come mantenere attive le pagine, vedere Durata della pagina e journal più avanti in questo argomento.

Per impostazione predefinita, il testo per ogni Page elemento visualizzato nell'elenco Pagine recenti di Internet Explorer è l'URI per .Page In molti casi questo testo non risulta molto significativo agli occhi dell'utente. Fortunatamente è possibile modificarlo tramite una delle opzioni seguenti:

  1. Valore dell'attributo associato JournalEntry.Name .

  2. Valore dell'attributo Page.Title .

  3. Valore dell'attributo Page.WindowTitle e URI per l'oggetto corrente Page.

  4. URI per l'oggetto corrente Page. (impostazione predefinita).

L'ordine nel quale sono elencate le opzioni corrisponde all'ordine di precedenza usato per cercare il testo. Ad esempio, se JournalEntry.Name è impostato, gli altri valori vengono ignorati.

Nell'esempio seguente viene usato l'attributo Page.Title per modificare il testo visualizzato per una voce journal.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.PageWithTitle"
    Title="This is the title of the journal entry for this page.">
</Page>
using System.Windows.Controls;

namespace SDKSample
{
    public partial class PageWithTitle : Page
    {

Namespace SDKSample
    Partial Public Class PageWithTitle
        Inherits Page
    }
}
    End Class
End Namespace

Anche se un utente può spostarsi nel journal usando le pagine Back, Forward e Recent Pages in Internet Explorer, è anche possibile spostarsi nel journal usando meccanismi dichiarativi e programmatici forniti da WPF. Un motivo per eseguire questa operazione è fornire interfacce utente di spostamento personalizzate nelle pagine.

È possibile aggiungere in modo dichiarativo il supporto di navigazione journal usando i comandi di spostamento esposti da NavigationCommands. Nell'esempio seguente viene illustrato come usare il comando di BrowseBack spostamento.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.NavigationCommandsPage">
<Hyperlink Command="NavigationCommands.BrowseBack">Back</Hyperlink>
<Hyperlink Command="NavigationCommands.BrowseForward">Forward</Hyperlink>
</Page>

È possibile spostarsi nel journal a livello di codice usando uno dei membri seguenti della NavigationService classe :

Il journal può anche essere modificato a livello di codice, come illustrato in Mantenimento dello stato del contenuto tramite cronologia di navigazione più avanti in questo argomento.

Durata della pagina e journal

Si consideri un XBAP con diverse pagine contenenti contenuti avanzati, tra cui grafica, animazioni e supporti. Il footprint di memoria per pagine simili può essere piuttosto grande, in particolare se vengono usati contenuti audio e video. Dato che il journal "ricorda" le pagine che sono state spostate a, tale XBAP potrebbe rapidamente consumare una grande e notevole quantità di memoria.

Per questo motivo, il comportamento predefinito del journal consiste nell'archiviare Page i metadati in ogni voce del journal anziché in un riferimento a un Page oggetto . Quando si passa a una voce journal, i relativi Page metadati vengono usati per creare una nuova istanza dell'oggetto specificato Page. Di conseguenza, ogni Page navigazione ha la durata illustrata nella figura seguente.

Page lifetime

Anche se l'uso del comportamento predefinito del journaling può ridurre il consumo di memoria, le prestazioni di rendering per pagina potrebbero essere ridotte; reinstantiing un Page può essere a elevato utilizzo di tempo, in particolare se ha un sacco di contenuto. Se è necessario conservare un'istanza Page nel journal, è possibile disegnare due tecniche per farlo. In primo luogo, è possibile passare a un Page oggetto a livello di codice chiamando il NavigationService.Navigate metodo .

In secondo luogo, è possibile specificare che WPF mantiene un'istanza di un Page oggetto nel journal impostando la KeepAlive proprietà su true (il valore predefinito è false). Come illustrato nell'esempio seguente, è possibile impostare KeepAlive in modo dichiarativo nel markup.

<Page
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.KeepAlivePage"
    KeepAlive="True">
  
  An instance of this page is stored in the journal.
  
</Page>

La durata di un oggetto Page mantenuto attivo è leggermente diverso da quello che non è. La prima volta che un Page oggetto mantenuto attivo viene spostato, viene creata un'istanza proprio come un Page oggetto che non viene mantenuto attivo. Tuttavia, poiché un'istanza Page di viene conservata nel giornale di registrazione, non viene mai creata un'istanza per tutto il tempo in cui rimane nel giornale di registrazione. Di conseguenza, se un oggetto ha una Page logica di inizializzazione che deve essere chiamata ogni volta Page che si passa a , è necessario spostarlo dal costruttore in un gestore per l'evento Loaded . Come illustrato nella figura seguente, gli Loaded eventi e Unloaded vengono comunque generati ogni volta che un Page oggetto viene spostato rispettivamente da e verso.

When the Loaded and Unloaded events are raised

Quando un oggetto Page non viene mantenuto attivo, non è consigliabile eseguire una delle operazioni seguenti:

  • Archiviare un riferimento all'oggetto o a parte di esso.

  • Registrare gestori eventi con eventi che non siano implementati dall'oggetto.

Eseguendo una di queste operazioni, verranno creati riferimenti che forzano la conservazione dell'oggetto Page in memoria, anche dopo che è stata rimossa dal journal.

In generale, è consigliabile preferire il comportamento predefinito Page di non mantenere attivo un oggetto Page . Ciò comporta tuttavia alcune implicazioni sullo stato che vengono trattate nella prossima sezione.

Mantenimento dello stato del contenuto tramite cronologia di navigazione

Se un oggetto Page non viene mantenuto attivo e dispone di controlli che raccolgono dati dall'utente, cosa accade ai dati se un utente si sposta da e torna all'oggetto Page? Dal punto di vista dell'esperienza utente, ci si potrebbe aspettare di visualizzare i dati immessi in precedenza. Sfortunatamente, poiché viene creata una nuova istanza di Page con ogni navigazione, i controlli raccolti vengono reinstanti e i dati vengono persi.

Fortunatamente, il journal fornisce supporto per memorizzare i dati tra Page gli spostamenti, inclusi i dati di controllo. In particolare, la voce journal per ogni Page elemento funge da contenitore temporaneo per lo stato associato Page . I passaggi seguenti illustrano come viene usato questo supporto quando si sposta un oggetto Page da:

  1. Viene aggiunta una voce per l'oggetto corrente Page al journal.

  2. Lo stato dell'oggetto Page viene archiviato con la voce journal per tale pagina, aggiunta allo stack posteriore.

  3. Il nuovo Page viene spostato su .

Quando si torna alla pagina Page , usando il journal, vengono distribuiti i passaggi seguenti:

  1. Viene Page creata un'istanza dell'elemento (la voce del journal superiore nello stack posteriore).

  2. L'oggetto Page viene aggiornato con lo stato archiviato con la voce journal per l'oggetto Page.

  3. L'oggetto Page viene spostato di nuovo a.

WPF usa automaticamente questo supporto quando i controlli seguenti vengono usati in un Pageoggetto :

Se un Page oggetto usa questi controlli, i dati immessi vengono memorizzati tra Page gli spostamenti, come illustrato dal coloreListBox preferito nella figura seguente.

Page with controls that remember state

Quando un oggetto Page dispone di controlli diversi da quelli dell'elenco precedente o quando lo stato viene archiviato in oggetti personalizzati, è necessario scrivere codice per fare in modo che il journal ricordi lo stato tra Page gli spostamenti.

Se è necessario ricordare piccole parti di stato tra Page gli spostamenti, è possibile usare le proprietà di dipendenza (vedere DependencyProperty) configurate con il flag di FrameworkPropertyMetadata.Journal metadati.

Se lo stato da Page ricordare tra gli spostamenti comprende più parti di dati, potrebbe risultare meno intensivo del codice per incapsulare lo stato in una singola classe e implementare l'interfaccia IProvideCustomContentState .

Se è necessario spostarsi tra vari stati di un singolo Pageoggetto , senza spostarsi dall'oggetto Page stesso, è possibile usare IProvideCustomContentState e NavigationService.AddBackEntry.

Cookie

Un altro modo in cui le applicazioni WPF possono archiviare i dati sono i cookie, che vengono creati, aggiornati ed eliminati usando i SetCookie metodi e GetCookie . I cookie che è possibile creare in WPF sono gli stessi cookie usati da altri tipi di applicazioni Web; i cookie sono parti arbitrarie di dati archiviati da un'applicazione in un computer client durante o tra sessioni dell'applicazione. I dati dei cookie assumono in genere la forma di una coppia nome/valore nel formato seguente.

Nome=Valore

Quando i dati vengono passati a SetCookie, insieme alla Uri posizione per cui deve essere impostato il cookie, viene creato un cookie in memoria ed è disponibile solo per la durata della sessione dell'applicazione corrente. Questo tipo di cookie viene definito cookie di sessione.

Per archiviare un cookie tra una sessione e l'altra dell'applicazione, occorre aggiungervi una data di scadenza nel formato seguente.

NOME=VALORE; expires=DAY, DD-MMM-YYYY HH:MM:SS GMT

Un cookie con una data di scadenza viene archiviato nella cartella File Internet temporanei dell'installazione di Windows corrente fino alla scadenza del cookie. I cookie di questo tipo sono definiti cookie permanenti perché permangono tra una sessione e l'altra dell'applicazione.

È possibile recuperare sia i cookie di sessione che i cookie permanenti chiamando il GetCookie metodo , passando la Uri posizione in cui è stato impostato il cookie con il SetCookie metodo .

Di seguito sono riportati alcuni dei modi in cui sono supportati i cookie in WPF:

  • Le applicazioni autonome WPF e gli XBAP possono creare e gestire i cookie.

  • È possibile accedere ai cookie creati da un XBAP dal browser.

  • Gli XBAP dello stesso dominio possono creare e condividere cookie.

  • Le pagine XBAP e HTML dello stesso dominio possono creare e condividere cookie.

  • I cookie vengono inviati quando XBAP e pagine XAML sciolte effettuano richieste Web.

  • Sia gli XBAP di primo livello che gli XBAP ospitati in IFRAMES possono accedere ai cookie.

  • Il supporto dei cookie in WPF è lo stesso per tutti i browser supportati.

  • In Internet Explorer, i criteri P3P relativi ai cookie vengono rispettati da WPF, in particolare per quanto riguarda gli XBAP di terze parti e di terze parti.

Navigazione strutturata

Se è necessario passare dati uno Page a un altro, è possibile passare i dati come argomenti a un costruttore non senza parametri di Page. Si noti che se si usa questa tecnica, è necessario mantenere attivo Page ; in caso contrario, la volta successiva che si passa a Page, WPF reinstantia Page usando il costruttore senza parametri.

In alternativa, è Page possibile implementare le proprietà impostate con i dati che devono essere passati. Le cose diventano complicate, tuttavia, quando un Page oggetto deve passare di nuovo i dati all'oggetto a cui è stato eseguito lo Page spostamento. Il problema è che la navigazione non supporta in modo nativo i meccanismi per garantire che un Page oggetto venga restituito dopo che è stato spostato da. In pratica, la navigazione non supporta la semantica di tipo chiamata/ritorno. Per risolvere questo problema, WPF fornisce la PageFunction<T> classe che è possibile usare per assicurarsi che venga restituito un oggetto Page in modo prevedibile e strutturato. Per altre informazioni, vedere Cenni preliminari sulla navigazione strutturata.

Classe NavigationWindow

Fino a questo punto sono stati analizzati i servizi di navigazione usati più di frequente per compilare applicazioni con contenuto navigabile. Questi servizi sono stati discussi nel contesto degli XBAP, anche se non sono limitati agli XBAP. I sistemi operativi moderni e le applicazioni Windows sfruttano l'esperienza del browser degli utenti moderni per incorporare lo spostamento in stile browser in applicazioni autonome. Esempi comuni prevedono:

  • Thesaurus di Word: navigazione in diversi vocaboli.

  • Esplora file: navigazione su file e cartelle.

  • Procedure guidate: suddivisione di un'attività complessa in più pagine tra le quali è possibile spostarsi. Un esempio è la Creazione guidata componenti di Windows che gestisce l'aggiunta e la rimozione di funzionalità di Windows.

Per incorporare lo spostamento in stile browser nelle applicazioni autonome, è possibile usare la NavigationWindow classe . NavigationWindow deriva da Window e lo estende con lo stesso supporto per lo spostamento fornito dagli XBAP. È possibile usare NavigationWindow come finestra principale dell'applicazione autonoma o come finestra secondaria, ad esempio una finestra di dialogo.

Per implementare , NavigationWindowcome con la maggior parte delle classi di primo livello in WPF (Window, Pagee così via), si usa una combinazione di markup e code-behind. come illustrato nell'esempio seguente.

<NavigationWindow
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    x:Class="SDKSample.MainWindow" 
    Source="HomePage.xaml"/>
using System.Windows.Navigation;

namespace SDKSample
{
    public partial class MainWindow : NavigationWindow
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }
}

Namespace SDKSample
    Partial Public Class MainWindow
        Inherits NavigationWindow
        Public Sub New()
            InitializeComponent()
        End Sub
    End Class
End Namespace

Questo codice crea un oggetto NavigationWindow che passa automaticamente a un Page oggetto (HomePage.xaml) all'apertura di NavigationWindow . NavigationWindow Se è la finestra principale dell'applicazione, è possibile usare l'attributo StartupUri per avviarlo. come illustrato nel markup seguente.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    StartupUri="MainWindow.xaml" />

Nella figura seguente viene illustrato come NavigationWindow finestra principale di un'applicazione autonoma.

A main window

Dalla figura è possibile notare che ha NavigationWindow un titolo, anche se non è stato impostato nel NavigationWindow codice di implementazione dell'esempio precedente. Il titolo viene invece impostato usando la WindowTitle proprietà , illustrata nel codice seguente.

<Page 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    Title="Home Page"
    WindowTitle="NavigationWindow">
</Page>

L'impostazione delle WindowWidth proprietà e WindowHeight influisce anche sull'oggetto NavigationWindow.

In genere, si implementa il proprio NavigationWindow quando è necessario personalizzarne il comportamento o l'aspetto. Se questo non è necessario, è possibile usare un'alternativa più rapida. Se si specifica l'URI pack di un Page oggetto come StartupUri in un'applicazione autonoma, Application crea automaticamente un NavigationWindow oggetto per ospitare l'oggetto Page. Il markup seguente illustra la procedura necessaria allo scopo.

<Application
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    StartupUri="HomePage.xaml" />

Se si desidera che una finestra dell'applicazione secondaria, ad esempio una finestra di dialogo sia , NavigationWindowè possibile usare il codice nell'esempio seguente per aprirla.

// Open a navigation window as a dialog box
NavigationWindowDialogBox dlg = new NavigationWindowDialogBox();
dlg.Source = new Uri("HomePage.xaml", UriKind.Relative);
dlg.Owner = this;
dlg.ShowDialog();
' Open a navigation window as a dialog box
Dim dlg As New NavigationWindowDialogBox()
dlg.Source = New Uri("HomePage.xaml", UriKind.Relative)
dlg.Owner = Me
dlg.ShowDialog()

La figura seguente mostra il risultato.

A dialog box

Come si può notare, NavigationWindow visualizza i pulsanti Indietro e Avanti di Internet Explorer che consentono agli utenti di spostarsi nel journal. L'esperienza utente è la stessa, come illustrato nella figura seguente.

Back and Forward buttons in a NavigationWindow

Se le pagine forniscono il supporto di spostamento del journal e l'interfaccia utente, è possibile nascondere i pulsanti Indietro e Avanti visualizzati NavigationWindow impostando il valore della ShowsNavigationUI proprietà su false.

In alternativa, è possibile usare il supporto per la personalizzazione in WPF per sostituire l'interfaccia utente stessa NavigationWindow .

Classe Frame

Sia il browser che NavigationWindow sono finestre che ospitano contenuto navigabile. In alcuni casi il contenuto delle applicazioni non deve essere necessariamente ospitato da un'intera finestra. Al contrario, tale contenuto può essere ospitato all'interno di altro contenuto. È possibile inserire contenuto navigabile in altri contenuti usando la Frame classe . Frame offre lo stesso supporto di NavigationWindow e XBAP.

Nell'esempio seguente viene illustrato come aggiungere un Frame oggetto a un Page oggetto in modo dichiarativo usando l'elemento Frame .

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page that Hosts a Frame"
  WindowWidth="250"
  WindowHeight="250">
<Frame Source="FramePage1.xaml" />
</Page>

Questo markup imposta l'attributo Source dell'elemento Frame con un URI pack per l'oggetto Page a cui Frame deve inizialmente passare. Nella figura seguente viene illustrato un XBAP con un oggetto con un PageFrame oggetto che è stato spostato tra più pagine.

A frame that has navigated between multiple pages

Non è necessario usare Frame solo all'interno del contenuto di un oggetto Page. È anche comune ospitare un Frame oggetto all'interno del contenuto di un oggetto Window.

Per impostazione predefinita, Frame usa solo il proprio giornale di registrazione in assenza di un altro giornale di registrazione. Se un Frame oggetto fa parte di contenuto ospitato all'interno di o di un NavigationWindow XBAP, Frame usa il journal appartenente a NavigationWindow o XBAP. A volte, tuttavia, potrebbe Frame essere necessario essere responsabile per il proprio giornale di registrazione. Un motivo per farlo è consentire lo spostamento nel journal all'interno delle pagine ospitate da un oggetto Frame. come illustrato nella figura seguente.

Frame and Page diagram

In questo caso, è possibile configurare l'oggetto Frame in modo che usi il relativo journal impostando la JournalOwnership proprietà di Frame su OwnsJournal. come illustrato nel markup seguente.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page that Hosts a Frame"
  WindowWidth="250"
  WindowHeight="250">
<Frame Source="FramePage1.xaml" JournalOwnership="OwnsJournal" />
</Page>

La figura seguente illustra l'effetto dell'esplorazione all'interno di un Frame oggetto che usa il proprio giornale di registrazione.

A frame that uses its own journal

Si noti che le voci del journal vengono visualizzate dall'interfaccia utente di spostamento in Frame, anziché da Internet Explorer.

Nota

Se un Frame oggetto fa parte di contenuto ospitato in un Windowoggetto , Frame usa il proprio journal e, di conseguenza, visualizza la propria interfaccia utente di spostamento.

Se l'esperienza utente richiede un Frame oggetto per fornire il proprio journal senza visualizzare l'interfaccia utente di spostamento, è possibile nascondere l'interfaccia utente di spostamento impostando su NavigationUIVisibilityHidden. come illustrato nel markup seguente.

<Page 
  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
  WindowTitle="Page that Hosts a Frame"
  WindowWidth="250"
  WindowHeight="250">
<Frame 
  Source="FramePage1.xaml" 
  JournalOwnership="OwnsJournal" 
  NavigationUIVisibility="Hidden" />
</Page>

Frame e NavigationWindow sono classi note come host di spostamento. Un host di navigazione è una classe in grado di spostarsi in un contenuto e visualizzarlo. A tale scopo, ogni host di spostamento usa il proprio NavigationService journal e . La figura seguente illustra la costruzione di base di un host di navigazione.

Navigator diagrams

In sostanza, ciò consente NavigationWindow e Frame di fornire lo stesso supporto di spostamento fornito da un XBAP quando è ospitato nel browser.

Oltre a usare NavigationService e un journal, gli host di spostamento implementano gli stessi membri implementati NavigationService . come illustrato nella figura seguente.

A journal in a Frame and in a NavigationWindow

Ciò consente di programmare un supporto specifico per la navigazione. È possibile considerare questa situazione se è necessario fornire un'interfaccia utente di navigazione personalizzata per un Frame oggetto ospitato in un oggetto Window. Inoltre, entrambi i tipi implementano membri aggiuntivi correlati alla navigazione, inclusi BackStack (NavigationWindow.BackStack, Frame.BackStack) e ForwardStack (NavigationWindow.ForwardStack, Frame.ForwardStack), che consentono di enumerare rispettivamente le voci del journal nello stack back e nello stack forward.

Come detto in precedenza, all'interno di un'applicazione possono essere presenti più journal. Nella figura seguente viene fornito un esempio in proposito.

Multiple journals within one application

In questo argomento Page sono stati usati pacchetti XBAP per illustrare le varie funzionalità di spostamento di WPF. Tuttavia, un oggetto Page compilato in un'applicazione non è l'unico tipo di contenuto a cui è possibile spostarsi e i pacchetti XBAP non sono l'unico modo per identificare il contenuto.

Come illustrato in questa sezione, puoi anche passare a file XAML separati, file HTML e oggetti.

Un file XAML libero è un file con le caratteristiche seguenti:

  • Contiene solo XAML (ovvero nessun codice).

  • Ha una dichiarazione dello spazio dei nomi appropriata.

  • Usa xaml come estensione di file.

Si consideri, ad esempio, il contenuto seguente archiviato come file XAML libero, Person.xaml.

<!-- Person.xaml -->
<TextBlock xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
  <TextBlock FontWeight="Bold">Name:</TextBlock>
  <TextBlock>Nancy Davolio</TextBlock>
  <LineBreak />
  <TextBlock FontWeight="Bold">Favorite Color:</TextBlock>
  <TextBlock>Yellow</TextBlock>
</TextBlock>

Se si fa doppio clic sul file, il browser si apre e passa al contenuto del file, visualizzandolo, come illustrato nella figura seguente.

Display of the content in the Person.XAML file

Puoi visualizzare un file XAML libero dai seguenti elementi:

  • Un sito Web nel computer locale, nell'Intranet o su Internet.

  • Una condivisione file UNC (Universal Naming Convention).

  • Disco locale.

È possibile aggiungere un file XAML libero ai preferiti del browser o essere la home page del browser.

Nota

Per altre informazioni sulla pubblicazione e l'avvio di pagine XAML sciolte, vedere Distribuzione di un'applicazione WPF.

Una limitazione rispetto al codice XAML libero consiste nel fatto che è possibile ospitare solo contenuto sicuro da eseguire con attendibilità parziale. Ad esempio, Window non può essere l'elemento radice di un file XAML libero. Per altre informazioni, vedere Sicurezza con attendibilità parziale in WPF.

Come ci si può aspettare, è anche possibile passare a HTML. È sufficiente fornire un URI che usa lo schema HTTP. Ad esempio, il codice XAML seguente mostra un Frame oggetto che passa a una pagina HTML.

<Frame Source="http://www.microsoft.com/default.aspx" />

Per passare al codice HTML sono necessarie autorizzazioni speciali. Ad esempio, non è possibile spostarsi da un XBAP in esecuzione nella sandbox di sicurezza parzialmente attendibile dell'area Internet. Per altre informazioni, vedere Sicurezza con attendibilità parziale in WPF.

Il WebBrowser controllo supporta l'hosting di documenti HTML, l'interoperabilità di script e script/codice gestito. Per informazioni dettagliate sul WebBrowser controllo, vedere WebBrowser.

Come Frame, passare al codice HTML usando WebBrowser richiede autorizzazioni speciali. Ad esempio, da un'applicazione parzialmente attendibile, è possibile passare solo al codice HTML che si trova nel sito di origine. Per altre informazioni, vedere Sicurezza con attendibilità parziale in WPF.

Se sono presenti dati archiviati come oggetti personalizzati, un modo per visualizzare i dati consiste nel creare un Page oggetto con contenuto associato a tali oggetti (vedere Panoramica del data binding). Se invece si preferisce evitare di creare un'intera pagina al solo scopo di visualizzare gli oggetti, è possibile spostarsi direttamente su di essi.

Si consideri la Person classe implementata nel codice seguente.

using System.Windows.Media;

namespace SDKSample
{
    public class Person
    {
        string name;
        Color favoriteColor;

        public Person() { }
        public Person(string name, Color favoriteColor)
        {
            this.name = name;
            this.favoriteColor = favoriteColor;
        }

        public string Name
        {
            get { return this.name; }
            set { this.name = value; }
        }

        public Color FavoriteColor
        {
            get { return this.favoriteColor; }
            set { this.favoriteColor = value; }
        }
    }
}

Namespace SDKSample
    Public Class Person
        Private _name As String
        Private _favoriteColor As Color

        Public Sub New()
        End Sub
        Public Sub New(ByVal name As String, ByVal favoriteColor As Color)
            Me._name = name
            Me._favoriteColor = favoriteColor
        End Sub

        Public Property Name() As String
            Get
                Return Me._name
            End Get
            Set(ByVal value As String)
                Me._name = value
            End Set
        End Property

        Public Property FavoriteColor() As Color
            Get
                Return Me._favoriteColor
            End Get
            Set(ByVal value As Color)
                Me._favoriteColor = value
            End Set
        End Property
    End Class
End Namespace

Per passare a esso, chiamare il NavigationWindow.Navigate metodo , 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="SDKSample.HomePage"
  WindowTitle="Page that Navigates to an Object">
<Hyperlink Name="hyperlink" Click="hyperlink_Click">
  Navigate to Nancy Davolio
</Hyperlink>
</Page>
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace SDKSample
{
    public partial class HomePage : Page
    {
        public HomePage()
        {
            InitializeComponent();
        }

        void hyperlink_Click(object sender, RoutedEventArgs e)
        {
            Person person = new Person("Nancy Davolio", Colors.Yellow);
            this.NavigationService.Navigate(person);
        }
    }
}

Namespace SDKSample
    Partial Public Class HomePage
        Inherits Page
        Public Sub New()
            InitializeComponent()
        End Sub

        Private Sub hyperlink_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)
            Dim person As New Person("Nancy Davolio", Colors.Yellow)
            Me.NavigationService.Navigate(person)
        End Sub
    End Class
End Namespace

La figura seguente mostra il risultato.

A page that navigates to a class

Da questa figura risulta evidente che non vengono visualizzati elementi utili. In effetti, il valore visualizzato è il valore restituito del ToString metodo per l'oggetto Person . Per impostazione predefinita, questo è l'unico valore che WPF può usare per rappresentare l'oggetto. È possibile eseguire l'override del ToString metodo per restituire informazioni più significative, anche se sarà ancora un valore stringa. Una tecnica che è possibile usare che sfrutta le funzionalità di presentazione di WPF consiste nell'usare un modello di dati. È possibile implementare un modello di dati che WPF può associare a un oggetto di un particolare tipo. Il codice seguente illustra un modello di dati per l'oggetto Person .

<Application
    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.App"
    StartupUri="HomePage.xaml">

  <Application.Resources>

    <!-- Data Template for the Person Class -->
    <DataTemplate DataType="{x:Type local:Person}">
      <TextBlock xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
        <TextBlock FontWeight="Bold">Name:</TextBlock>
        <TextBlock Text="{Binding Path=Name}" />
        <LineBreak />
        <TextBlock FontWeight="Bold">Favorite Color:</TextBlock>
        <TextBlock Text="{Binding Path=FavoriteColor}" />
      </TextBlock>
    </DataTemplate>
    
  </Application.Resources>

</Application>

In questo caso, il modello di dati è associato al Person tipo usando l'estensione x:Type di markup nell'attributo DataType . Il modello di dati associa TextBlock quindi gli elementi (vedere TextBlock) alle proprietà della Person classe . Nella figura seguente viene illustrato l'aspetto aggiornato dell'oggetto Person .

Navigating to a class that has a data template

Un vantaggio di questa tecnica è dato dalla coerenza: il modello di dati può infatti essere usato di nuovo per visualizzare gli oggetti in modo coerente nell'intero ambito dell'applicazione.

Per altre informazioni sui modelli di dati, vedere Cenni preliminari sui modelli di dati.

Sicurezza

Il supporto dello spostamento WPF consente di passare da XBAP a Internet e consente alle applicazioni di ospitare contenuto di terze parti. Per proteggere le applicazioni e gli utenti da comportamenti dannosi, WPF offre un'ampia gamma di funzionalità di sicurezza descritte in Sicurezza e sicurezza parzialmente attendibile WPF.

Vedi anche