La mobilità innanzitutto

Esplorazione di Windows Phone: nozioni di base

Yochay Kiriaty

Scarica il codice di esempio

Le applicazioni Silverlight per Windows Phone presentano un modello analogo a una pagina Web in cui gli utenti finali possono spostarsi da una pagina all'altra. Un pulsante hardware dedicato (Indietro) consente di passare agevolmente alle pagine precedenti senza occupare spazio sulla schermata, mentre l'inserimento nel journal (o cronologia) degli spostamenti è integrato nella piattaforma per garantire il passaggio da una pagina all'altra o lo spostamento tra varie applicazioni. In questo articolo in due parti verranno trattati gli argomenti seguenti:

  • Introduzione al modello di esplorazione delle pagine in Windows Phone.
  • Procedure consigliate per utilizzare al meglio le API correnti (integrazione con il pulsante hardware Indietro, ottimizzazione del caricamento e del download di pagine, conformità del modello di esplorazione alle linee guida di certificazione Windows Phone).
  • Procedure azionabili e semplici da seguire per creare gli spostamenti più complessi non implementati con le API correnti, tra cui contenuti temporanei e transizioni di pagine.

Modello di esplorazione di Windows Phone

Il modello di esplorazione di Windows Phone è costituito da un frame (PhoneApplicationFrame) e una o più pagine (PhoneApplicationPage) con i contenuti caricati nel frame.

PhoneApplicationFrame espone la maggior parte degli eventi di esplorazione e il metodo Navigate utilizzato per scorrere la pagine. Determina inoltre l'area client per l'applicazione e riserva spazio per la barra delle applicazioni e l'area di notifica. 

PhoneApplicationPage invia notifiche specifiche quando l'utente visita una pagina e quando passa ad altre pagine. Gestisce inoltre gli eventi relativi al pulsante hardware Indietro.

PhoneApplicationFrame e PhoneApplicationPage condividono NavigationService, il servizio che consente l'esplorazione. In Windows Phone è supportata la funzionalità di inserimento nel journaling, che consente di tenere traccia della cronologia delle pagine caricate per poter accedere agevolmente a una pagina già visualizzata, e le API sono esposte per poter tornare indietro con la visualizzazione. L'esplorazione in avanti non è supportata nel telefono.

Windows Phone dispone di tre pulsanti hardware dedicati: Indietro, Start e Cerca. La gestione del pulsante hardware Indietro presenta specifici requisiti relativi alla certificazione dell'applicazione:

  • L'utente di un'applicazione deve essere in grado di passare a una pagina precedente. L'unica eccezione possibile è rappresentata da una richiesta di conferma che determinerebbe una perdita di dati: una volta espressa la conferma, l'utente potrà scegliere di passare alla pagina precedente.
  • Se è aperto un popup, il riquadro di input software o un'altra finestra di dialogo temporanea, il pulsante hardware Indietro deve consentire di chiudere l'elemento e mantenere la pagina corrente (senza quindi spostare l'utente alla pagina precedente).
  • La pressione del pulsante Indietro nella schermata iniziale di un'applicazione determina la chiusura dell'applicazione. Questa funzionalità è gratuita. Se l'esplorazione non viene impedita, l'applicazione viene chiusa dal framework (si tratta dell'unico modo per chiudere un'applicazione Silverlight). Nelle API esposte non è disponibile il metodo Exit.
  • Per garantire un'esperienza utente coerente tra le varie applicazioni, il pulsante Indietro deve essere utilizzato solo per l'esplorazione delle pagine precedenti.

Oltre al pulsante Indietro, anche il pulsante Start gioca un ruolo essenziale nell'esplorazione. Se l'utente preme il pulsante Start, verrà disattivata l'applicazione in uso e verrà eseguito un cambio di contesto in fase di spostamento in avanti nel menu Start. Da qui un utente può avviare ed esplorare un'altra applicazione oppure scegliere di tornare all'applicazione precedente utilizzando il pulsante hardware Indietro. Ne risulterà un modello di esplorazione in il pulsante Indietro consente di passare alle pagine di un'applicazione in uso o di un'applicazione utilizzata in precedenza.

API di Windows Phone

Come già indicato, gli elementi essenziali dell'esplorazione sono PhoneApplicationFrame e PhoneApplicationPage.

PhoneApplicationFrame funge da RootVisual per l'applicazione. All'avvio viene creata un'istanza di PhoneApplicationFrame nella classe App in App.xaml.cs (vedere la Figura 1).

Figura 1 Creazione di un'istanza di RootFrame in App.xaml.cs

private void InitializePhoneApplication()
{
  if (phoneApplicationInitialized)
        return;

  // Create the frame but don't set it as RootVisual yet; this allows the splash
  // screen to remain active until the application is ready to render.
  RootFrame = new PhoneApplicationFrame();
  RootFrame.Navigated += CompleteInitializePhoneApplication;

           
  // Handle navigation failures
  RootFrame.NavigationFailed += RootFrame_NavigationFailed;

  // Ensure we don't initialize again
  phoneApplicationInitialized = true;
}

Il runtime passa automaticamente all'istanza di PhoneApplicationPage, specificata dall'attributo NavigationPage in DefaultTask nel manifesto dell'applicazione WMAppManifest.xml, come indicato qui:

<Tasks>
  <DefaultTask  Name ="_default" NavigationPage="MainPage.xaml"/> 
</Tasks>

Per quanto riguarda responsabilità e API, PhoneApplicationFrame espone la maggior parte degli eventi e dei metodi di esplorazione necessari in questo articolo. Nella figura 2 vengono elencati i metodi, le proprietà e gli eventi più importanti in PhoneApplicationFrame.

Figura 2 Metodi, proprietà ed eventi in PhoneApplicationFrame

Nome Tipo Descrizione
Navigate Metodo Consente di passare a un nuovo elemento PhoneApplicationPage specificato dal parametro URI. Il parametro è un URI e pertanto una chiamata Navigate creerà un'istanza della nuova pagina per esplorarla (l'utente non passerà a un'istanza di pagina già creata).
CanGoBack Proprietà di sola lettura Restituisce true se lo stack Indietro dell'applicazione (cronologia/inserimento nel journaling) non è vuoto, a significare che gli utenti devono aver eseguito l'esplorazione in avanti almeno una volta nell'applicazione. Se l'applicazione è nella prima pagina caricata nell'applicazione, CanGoBack restituirà false e non sarà possibile chiamare GoBack a livello di codice, ma l'utente finale potrà comunque premere il pulsante hardware Indietro per chiudere l'applicazione, poiché tornerà all'applicazione eseguita in precedenza.
CanGoForward Proprietà di sola lettura Non applicabile a Windows Phone. Restituisce sempre false, poiché l'esplorazione in avanti non è supportata.
UriMapper Proprietà Ottiene/imposta un UriMapper. Fuori ambito per l'articolo, ma è opportuno segnalare il supporto del mapping URI.
GoBack Metodo Consente di passare alla voce più recente nello stack Indietro. Il metodo genererà un'eccezione se non sono presenti voci nello stack Indietro; controllare sempre CanGoForward prima di chiamare il metodo.
GoForward Metodo Non supportato in Windows Phone; verrà generata l'eccezione InvalidOperationException
Navigating Evento Si verifica in caso di una nuova richiesta di esplorazione. A questo punto può comunque essere annullato impostando la proprietà Cancel nel parametro NavigatingCancelEventArgs su true. Per conoscere i motivi per cui non annullare le esplorazioni delle pagine precedenti, consultare le note più avanti nell'articolo.
Navigated Evento Si verifica se è stata eseguita un'esplorazione. Il contenuto della pagina esplorata potrebbe non essere ancora stato caricato: l'evento si verifica semplicemente una volta rilevato ed esplorato il contenuto.
NavigationFailed Evento Si verifica in caso di errore.
NavigationStopped Evento Si verifica in caso di arresto dell'esplorazione chiamando il metodo StopLoading o più comunemente se è richiesta una nuova esplorazione mentre la precedente è in esecuzione.

In gran parte vengono ereditati da Frame e risulteranno pertanto familiari a chi ha già utilizzato in passato la classe Silverlight Frame. L'elenco nella Figura 2 non include tutte le funzionalità di PhoneApplicationFrame, ma solo quelle pertinenti all'esplorazione.

Descrizione del codice: per osservare tutti gli eventi e le proprietà in azione, esplorare il file AllNavigationsEvents.xaml.cs nel codice di esempio contenuto in questo articolo. È inoltre possibile visualizzare l'ordine di attivazione degli eventi nella Figura 3.

image: ng>The Sequence of Events as You Navigate Across Pages

Figura 3 Sequenza di eventi durante l'esplorazione delle pagine

PhoneApplicationFrame determina inoltre l'area client per l'applicazione e riserva spazio per la barra delle applicazioni e l'area di notifica. Questo dettaglio risulterà determinante durante l'esplorazione delle pagine contenenti una barra delle applicazioni, poiché è specificata a livello della pagina, e un'animazione a livello di sistema consentirà di visualizzare e nascondere la barra in fase di caricamento della pagina.

Il secondo componente di esplorazione è PhoneApplicationPage, che ricopre due ruoli fondamentali:

  • Gestione delle pressioni del pulsante hardware Indietro
  • Distribuzione di eventi per il ciclo di vita di una pagina per sapere quando è attivata o disattivata.

Per l'integrazione con il pulsante hardware Indietro, PhoneApplicationPage espone un evento BackKeyPress. La pagina presenta inoltre un metodo OnBackKeyPress di cui è possibile eseguire l'override nell'istanza di una pagina per gestire e persino annullare un evento di pressione del pulsante Indietro.

PhoneApplicationFrame presenta un evento Navigating e una notifica/callback OnNavigatingFrom. Con questi elementi è possibile annullare le esplorazioni di altre pagine all'interno dell'applicazione impostando e.Cancel su true nel parametro NavigationCancelEventArgs passato a questi metodi; a causa di un bug noto nella piattaforma, non annullare le esplorazioni del pulsante Indietro da questi eventi o metodi. Se si annulla la pressione del pulsante Indietro in questo evento, l'esplorazione verrà interrotta e sarà necessario riavviare l'applicazione. Gli unici due metodi consigliati per annullare la pressione di un pulsante hardware Indietro sono rappresentati dall'evento BackKeyPress di PhoneApplicationPage e dal callback OnBackKeyPress.

Nella Figura 4 sono elencati gli eventi e i metodi in cui è possibile annullare le esplorazioni, con consigli sull'opportunità o meno di annullare la pressione del pulsante Indietro nel metodo specificato e sui modi per controllare se l'evento corrisponde all'esplorazione di pagine precedenti.

Figura 4 Eventi e metodi in cui è possibile annullare le esplorazioni

Proprietario Evento/notifica Può annullare una nuova esplorazione Può annullare esplorazioni precedenti Controllo di esplorazioni precedenti
PhoneApplicationFrame Navigating No Sì; controllo di e.NavigationMode != NavigationMode.Back
PhoneApplicationPage OnNavigatingFrom No Sì; controllo di e.NavigationMode != NavigationMode.Back
PhoneApplicationPage OnBackKeyPress No (chiamato solo alla pressione del pulsante Indietro) Non necessario. Chiamato solo alla pressione del pulsante Indietro
PhoneApplicationPage BackKeyPress (evento) No (chiamato solo alla pressione del pulsante Indietro) Non necessario. Chiamato solo alla pressione del pulsante Indietro

PhoneApplicationPage integra questi eventi per completare il ciclo di vita dell'esplorazione con i callback dei metodi OnNavigatedTo e OnNavigatedFrom più utili per la pagina. Per comprendere meglio e ricordare senza difficoltà quando vengono chiamati questi callback, è opportuno completare i nome dei metodi con la denominazione "this page". Un metodo viene chiamato quando l'utente ha esplorato la pagina ("navigated to this page"), quindi l'altro metodo viene chiamato quando l'utente è passato da questa pagina ("navigated from this page") a un'altra pagina.

Nella Figura 3 è illustrata la sequenza degli eventi in fase di esplorazione delle pagine. La simmetria tra NavigatedTo e NavigatedFrom rende i due metodi ideali per avviare e arrestare le operazioni necessarie quando la pagina è visibile e superflue quando la pagina è nello stack Indietro. NavigatedTo viene inoltre sempre avviato prima del caricamento di una pagina. È dunque errato supporre che i contenuti della pagina vengano caricati in questa fase.

OnNavigatedTo e OnNavigatedFrom risultano fondamentali per Windows Phone per via dello stack Indietro. Il sistema operativo mantiene lo stack Indietro per le pagine a cui è possibile tornare e pertanto le pagine non vengono immediatamente scaricate, eliminate o sottoposte a Garbage Collection nel momento in cui si passa da una pagina a un'altra. Le pagine vengono in realtà spostate nello stack Indietro e mantenute nella memoria. Quando l'utente fa clic sul pulsante Indietro per tornare alla pagina, quest'ultima verrà aggiunta all'albero visuale e non verrà ricreata, a meno che l'applicazione non sia stata disattivata e definitivamente rimossa nel momento che intercorre tra il passaggio a un'altra pagina e la pressione del pulsante Indietro. Poiché non è supportata la funzionalità di inserimento nel journaling per le pagine successive, le pagine possono essere sottoposte a Garbage Collection solo quando si passa a una pagina precedente, a condizione che non siano presenti altri riferimenti a questa pagina.

Nella Figura 5 è illustrato un diagramma del ciclo di vita di PhoneApplicationPage.

image: The PhoneApplicationPage Lifecycle

Figura 5 Ciclo di vita di PhoneApplicationPage

Passando da Page1 a Page2 e quindi a Page3, le pagine non verranno sottoposte a Garbage Collection finché non verrà chiamato il metodo GoBack dalla pagina. Le pagine inattive sono nello stack Indietro, ma comunque in memoria. Se sono in ascolto di eventi globali, i listener di eventi sono ancora attivi.

Sebbene una pagina da cui si esegue l'esplorazione non venga sottoposta a Garbage Collection, non sarà più visibile o attiva finché non si tornerà a visualizzarla. Quando un utente passa a un'altra pagina, è pertanto opportuno eseguire la pulizia e liberare eventuali risorse dispendiose. Se ad esempio si ascoltano modifiche di ubicazioni geografiche mediante GeoCoordinateWatcher, è opportuno arrestare il listener in OnNavigatedFrom e riavviarlo quando l'utente tornerà alla pagina (e verrà chiamata la pagina OnNavigatedTo).

Descrizione del codice: per osservare in che modo le pagine vengono conservate nella memoria mentre si trovano nello stack Indietro, esplorare la pagina GarbageCollectedSample inclusa nel download del codice di questo articolo. Nella memoria viene mantenuto un calcolo incrementale delle pagine, che aumenterà man mano che vengono esplorate nuove pagine e diminuirà quando vengono esplorate le pagine precedenti.

Termina qui la prima parte della nostra serie. Il prossimo mese ci concentreremo su argomenti di esplorazione avanzata.

Yochay Kiriaty è un Senior Technical Evangelist presso Microsoft, specializzato in tecnologie client quali Windows e Windows Phone. È coautore dei testi "Introducing Windows 7 for Developers" (Microsoft Press, 2009) e "Learning Windows Phone Programming" (O'Reilly Media, 2011).

Jamie Rodriguez è un Principal Evangelist presso Microsoft che promuove l'adozione di nuove tecnologie client quali Silverlight e Windows Phone. È possibile contattarlo su Twitter (@jaimerodriguez) o all'indirizzo blogs.msdn.com/jaimer.

Un ringraziamento al seguente esperto tecnico per la revisione dell'articolo: Peter Torr