...

DispenseWP - Concetti chiave (2240416 byte)

by user

on
Category: Documents
7

views

Report

Comments

Transcript

DispenseWP - Concetti chiave (2240416 byte)
+
Navigazione fra pagine
Nicolò Sordoni
+ Window, Frame, Page
In tutte le applicazioni Windows, sia le Store Apps, che le Phone
Apps, esistono i seguenti concetti:

Window (finestra), che non è altro che una porzione dello
schermo. In Windows Phone, un’app ha una sola finestra, mentre
le App Windows Store possono averne molteplici.

Frame: Ogni Window può contenere un solo Frame, la cui
dimensione è identica a quella della finestra. Il Frame viene
creato all’avvio dell’applicazione, mostra la pagina corrente e
mantiene in memoria lo stack contenente la cronologia di
navigazione
+ Window, Frame, Page

Page: La pagina è il concetto chiave delle nostre applicazioni,
ed è quel componente che corrisponde ad una singola
schermata della nostra app. Al suo interno possiamo definire
l’interfaccia, la logica di interazione utente, ecc..
+ Application Life Cycle
In figura è mostrato il ciclo di vita delle applicazioni Windows
Phone. Ogni app in esecuzione si trova in uno stato denominato
Running; in qualsiasi momento si può verificare un evento
(pressione del tasto Home, selezione di una notifica) che porta
l’app ad essere sospesa. L’app passa innanzitutto nello stato
Deactivated in cui il sistema esegue una serie di operazioni
per ridurre l’impatto su memoria, batteria e CPU.
+ Application Life Cycle
A questo punto l’app viene portata in uno stato denominato
Dormant, in cui sono stati interrotti tutti i thread in background,
sono state annullate le notifiche dei sensori ed è stato
effettuato il dispose delle risorse non ritenute necessarie per
un’applicazione non attiva.
Lo stato dell’applicazione (Stack delle pagine, pagina attuale e
dati contenuti al suo interno) viene però mantenuto, pertanto,
riportandola in foreground, l’app rimarrà identica a quando
l’abbiamo sospesa. Per tornare in background l’app passerà
tramite lo stato Activated, in cui saranno ripristinate alcune
delle funzionalità che erano state interrotte (es: sensori),
sebbene non tutte. Ad esempio, i thread in background,
dovranno essere riavviati da codice.
+ Application Life Cycle
Sebbene il sistema gestisca per noi la persistenza dello stato
della nostra app, non possiamo sempre far affidamento al
100% su tale meccanismo, dato che, come si nota
dall’immagine che rappresenta il ciclo di vita, l’app può
passare dallo stato Dormant a TombStoned. In tal caso lo stato
della nostra app andrebbe perso, pertanto è buona norma
memorizzare in maniera persistente lo stato, ogni volta che la
nostra app viene posta in background.
+ Gestire la navigazione
Come accennato, il componente responsabile di gestire la
navigazione fra le varie pagine è il Frame, pertanto, per poter
spostarci in una pagina abbiamo bisogno di utilizzare tale
classe.
All’interno di ogni pagina, abbiamo accesso diretto al frame
che la contiene, grazie alla proprietà denominata, come
possiamo intuire, Frame. Tale classe espone due overload del
metodo Navigate, che ci permettono di navigare verso una
differente pagina dell’app.
La presenza di due differenti overload del metodo è dovuta
all’eventuale necessità di passare un parametro alla nuova
Page che andremo a visualizzare.
+ Frame.Navigate

Frame.Navigate(Type sourcePageType);

Frame.Navigate(Type sourcePageType, object parameter);
Come possiamo notare, il metodo Navigate richiede come
primo parametro un Type, cioè un tipo. Tale tipo deve essere
quello della nuova pagina che vogliamo mostrare, pertanto la
sintassi è la seguente:
L’esempio precedente permette di navigare ad una nuova
pagina, denominata SecondPage, a cui viene passato un
oggetto come parametro. Tale oggetto può essere di qualsiasi
tipo (Stringa, Intero,una qualunque classe definita dall’utente,
ecc...).
+ metodo OnNavigateTo
Ovviamente, dopo aver passato un parametro alla pagina che
viene lanciata, è necessario che quest’ultima sia in grado di
recuperarlo per poterlo utilizzare. A tale scopo ogni pagina
espone un apposito metodo di callback, cioè OnNavigateTo.
Tale metodo viene invocato nel momento in cui viene effettuata
una navigazione verso la pagina corrente, prima che sia
mostrata a video.
Come si nota dall’esempio, tale metodo accetta come parametro
un’istanza della classe NavigationEventArgs, che permette di accedere ai
parametri ottenuti in input tramite la property Parameter.
Questo è il punto ideale in cui ripristinare lo stato della nostra pagina, in
caso di chiusura improvvisa.
+ metodo OnNavigatedFrom
Oltre al metodo OnNavigatedTo, ne esiste un altro, speculare al
primo, per gestire il caso in cui l’utente esca dalla pagina.
Il parametro e ci permette di ottenere informazioni riguardo
alla pagina alla quale stiamo per accedere.
Tale metodo è il punto ideale in cui salvare lo stato e
deallocare risorse non necessarie quando la pagina non è
visualizzata, rimuovere eventuali Handler (come vedremo a
breve), ecc..
+ Tornare alla pagina precedente
La classe Frame mantiene al suo interno la cronologia di
navigazione, consentendo quindi in ogni momento di tornare
alla pagina precedente. Il metodo da invocare è
Frame.GoBack(). Dato che non sempre possiamo essere certi
che esista una pagina precedente, è buona norma effettuare
tale verifica, sfruttando la proprietà booleana
Frame.CanGoBack.
+ Gestire la pressione del tasto back
Una cosa a cui va prestata particolare attenzione, è l’utilizzo del
tasto back. Il comportamento di default del sistema, nel
momento in cui l’utente preme il tasto back, è quello di
rimandarlo all’applicazione precedente. Pertanto la nostra
app sarà posta in background per passare ad un’altra. Non
sempre questo è il comportamento che desideriamo ottenere,
dato che potremmo voler fare in modo che, premendo il tasto
back, l’utente torni alla pagina precedente.
+ Tasto Back: Override a livello di
App
Sovrascrivere la pressione del tasto back a livello di App, ci
permette di far si che ogni volta che l’utente preme back, non
sarà il sistema a gestirlo, ma il metodo che avremo
appositamente predisposto. In tal modo possiamo far sì che il
comportamento di default sia quello di ritornare alla pagina
precedente, gestendo il tutto in un unico punto del codice,
senza doverlo ripetere per ogni pagina.
Per ottenere tale risultato, è necessario sovrascrivere il
comportamente di default del sistema. Il punto per farlo è
all’avvio, quindi all’interno del costruttore della classe App.
+ Tasto Back: Override a livello di
App
Analizziamo il metodo che abbiamo definito per definire il
nostro comportamento personalizzato. Innanzitutto utilizziamo
la proprietà Window.Current.Content, per accedere
innanzitutto alla finestra Corrente, che in WP è unica per ogni
applicazione, e quindi al suo Content (cioè il Frame dell’app).
Dopo aver verificato che tale frame esista, abbiamo gestito il
ritorno alla Page precedente.
+ Tasto Back: Override a livello di
Page
L’utilizzo del back a livello di singola pagina è necessario in
quei casi in cui abbiamo molteplici azioni che possono essere
annullate tramite il tasto back. Il caso classico è quello in cui la
nostra pagine presenta all’utente una finestra pop-up. In questo
caso, potremmo voler fornire all’utente la possibilità di
chiuderla tramite la pressione del back.
Il codice nella seguente slide mostra come gestire tale
situazione. Nel momento in cui l’utente accede alla pagina, è
necessario aggiungere all’evento BackPressed, un apposito
Handler. E’ importante rimuovere tale Handler in uscita dalla
pagina, per evitare di invocare molteplici volte lo stesso
metodo (in caso di accesso multiplo alla pagina) e di invocare
il metodo anche dopo che la pagina non sarà più visualizzata.
+ Tasto Back: Override a livello di
Page
+ Page CacheMode
Nel momento in cui l’utente abbandona una determinata
pagina, il sistema ha 2 possibilità: mantenerla in cache, oppure
terminarla. Tale scelta dipenderà dall’attributo
NavigationCacheMode, che avremo settato in tale Page:

NavigationCacheMode.Disabled : ogni volta che la pagina
viene visualizzata, viene creata una nuova istanza da capo.

NavigationCacheMode.Enabled : il sistema mantiene in
cache la pagina, ma può essere scartata se la dimensione
della cache per il Frame corrente supera una determinata
dimensione (determinata dalla proprietà Frame.CacheSize).

NavigationCacheMode.Required : la pagina viene sempre e
comunque mantenuta in cache.
+ Utilities: SuspensionManager e
NavigationHelper
Per aiutarci a preservare lo stato della nostra app, anche
quando va in background, Microsoft ci mette a disposizione
due classi di supporto:

SuspensionManager : memorizza lo stato del nostro frame e
ci permette di ripristinare lo stack delle pagine e di ritornare
alla pagina corrente.

NavigationHelper : ci permette di memorizzare informazioni
riguardo alla pagina correntemente visualizzata, in modo da
mantenere le informazioni anche se l’app viene terminata.
+ Utilities: SuspensionManager e
NavigationHelper
Tali classi vengono aggiunte in automatico quando inseriamo,
all’interno del progetto, una nuova pagina di tipo BasicPage :
Solution > Add > New Item.. e, dalla finestra che appare,
selezioniamo Basic Page.
Verremo informati che il sistema sta per aggiungere in
automatico alcune nuove classi. Accettiamo e vedremo che
comparirà una nuova sezione all’interno della nostra app,
denominata Common.
+ SuspensionManager
Il SuspensionManager, deve registrare al suo interno il Frame
dell’applicazione corrente; il punto ideale per farlo è non
appena è stato creato. Pertanto, per utilizzare il
SuspensionManager, è sufficiente lavorare all’interno della
classe App, dato che è in questo punto che vengono gestiti i
principali eventi relativi al Frame.
Il metodo onLaunched, viene invocato quando l’app viene
lanciata per la prima volta. In questo metodo, che l’IDE ha già
generato per noi con del codice all’interno, quello che l’app
cerca di fare è recuperare il riferimento al Frame corrente; Se
non riesce a recuperarlo, viene creata una nuova istanza. In
questo punto andremo a registrare il Frame appena istanziato
nel SuspensionManager e a cercare di ripristinare l’istanza
precedente.
+ SuspensionManager
L’esempio precedente mostra come applicare quanto detto nella
precedente slide, mentre quello che segue, rappresenta il codice per
recuperare lo stato precedentemente salvato. Il metodo onSuspending
è invocato quando l’app viene messa in background
+ await e async
Negli esempi precedenti è stato fatto uso di due parole chiave
finora mai incontrate: await e async. Esse sono due nuove parole
chiave, introdotte di recente da Microsoft, per gestire l’utilizzo di
codice asincrono.
async deve essere prefissa a tutte quelle chiamate che, dato che
potrebbero richiedere molto tempo per essere eseguite,
andrebbero lanciate in maniera asincrona. Usando la parola
chiave async, viene invocato un metodo in maniera asincrona;
nello stesso momento il metodo attualmente in esecuzione viene
interrotto, ed il Thread ritorna disponibile per nuove operazioni;
dato che solitamente si tratta del GUI Thread, in tal modo si
impedisce che l’interfaccia rimanga bloccata. Non appena la
chiamata asincrona sarà terminata, il controllo ritornerà al metodo
precedente che completerà la sua esecuzione.
async è una parola chiave che deve essere prefissa a tutti quei
metodi che fanno uso di codice asincrono.
+ NavigationHelper
Come accennato, esiste un componente che ci supporta nel
mantenere persistente lo stato di una singola pagina. Per farlo
dobbiamo dichiarare a livello d’istanza una nuova proprietà di
tipo NavigationHelper, che andremo ad inizializzare nel
costruttore della pagina.
Oltre a questo è necessario invocare due metodi di Utility
all’interno dei callback OnNavigatedTo e OnNavigatedFrom
+ NavigationHelper
Questa classe offre due eventi, LoadState e SaveState, che vengono
invocati rispettivamente quando la pagina viene caricata oppure
chiusa. All’interno dei metodi associati a tali eventi, andremo a
scrivere il codice che ci permetterà di preservare lo stato della
pagina.
+
Controlli specifici
dell’ambiente
Nicolò Sordoni
+ L’ApplicationBar
In Windows Phone si fa spesso uso della cosiddetta
ApplicationBar, che non è altro che una barra, che viene
visualizzata in basso, a fondo alla pagina, e permette un rapido
accesso a determinate funzionalità dell’applicazione.
I bottoni inseriti al suo interno sono divisi in due categorie:

Primari, che possiedono un’icona che è sempre visualizzata, ed
un testo, che viene mostrato solamente quando la barra viene
espansa. Possono essere al massimo 4

Secondari, di default sono nascosti e diventano visibili
all’espansione della barra.
La barra di default mostra solamente le icone dei bottoni primari,
ma è sempre presente un tasto che consente all’utente
l’espansione della barra.
+ L’ApplicationBar
+ L’ApplicationBar
Per inserire una barra all’interno di una pagina, è necessario
utilizzare la proprietà Page.BottomAppBar. I bottoni vanno definiti
all’interno di un nodo innestato al suo interno, denominato
CommandBar.
Il nodo CommandBar prevede al suo interno una suddivisione in
due categorie: CommandBar.PrimaryCommands e
CommandBar.SecondaryCommands, per definire rispettivamente
bottoni primari e secondari.
All’interno di tali sezioni andremo ad inserire i bottoni veri e
propri, utilizzando il controllo AppBarButton.
+ AppBarButton
Il controllo AppBarButton permette di definire un elemento che
sarà mostrato all’interno dell’ApplicationBar. Le principali
proprietà di tale controllo sono:

Icon : Valida solamente nel caso di PrimaryCommand. Specifica
quale icona sarà mostrata all’interno del cerchio per quel
bottone. E’ possibile selezionarla fra un elenco di icone di
default offerte da sistema, oppure utilizzare una propria icona
personalizzata.

Label : Specifica il testo che sarà associato al bottone e che sarà
visualizzato in maniera differente a seconda di che tipo di
bottone si tratti.

Click : E’ un evento e permette di gestire il click sul bottone.
+ AppBarButton
+ Hub
+ Hub
L’immagine alla slide precedente ci mostra un classico utilizzo di
una pagina strutturata come Hub. La schermata è ovviamente più
ampia della dimensione dello schermo di uno smartphone; questo
perchè le varie sezioni (indicate come Panorama Panels),
dovranno essere visualizzate una alla volta. L’utente potrà
scorrerle semplicemente tramite uno swipe. La navigazione è
circolare, quindi una volta arrivati all’ultima sezione, uno slide
verso destra ci permetterà di tornare alla prima.
La cosa che salta subito all’occhio in questo tipo di applicazione è
l’immagine di sfondo. Questo tipo di applicazione presenta
un’unica immagine come sfondo per tutte le sezioni, quindi
scorrendo da un panel all’altro, scorrerà anche l’immagine. Spesso
si fa uso di immagini circolari, in cui il margine destro coincide
con quello sinistro, quindi non si ha mai un taglio netto, neanche
quando si passa dall’ultimo Panel al primo.
Notiamo come anche il titolo sia distribuito su più sezioni, per
sottolineare la presenza di ulteriori informazioni.
+ Hub
Ognuna delle sezioni di questo pattern non è vincolata in alcun
modo alle altre, ma è libera di mostrare qualsiasi tipo di
informazione. Ovviamente è necessario che le varie viste abbiano
comunque un target comune, altrimenti non avrebbero motivo di
trovarsi nella stessa pagina.
Questo tipo di pattern viene utilizzato molto per realizzare le
schermate iniziali delle applicazioni, fungendo per certi versi da
vetrina. In questo modo è possibile presentare all’utente le
funzionalità principali e più interessanti in una maniera
accattivante.
Ciò che è importante tenere a mente è che questo pattern non è
stato concepito come contenitore di dati, ma esclusivamente come
punto di accesso a ulteriori funzionalità. E’ pertanto sconsigliato,
sia dal punto di vista dell’esperienza utente, che delle
performance, inserire troppe informazioni in un Hub. Microsoft
suggerisce di non usare più di 5 sezioni.
+ Pivot
+ Pivot
Il pivot, come il panorama, è suddiviso in più sezioni, che possono
essere navigate tramite swipe. Anche in questo caso si ha
circolarità di navigazione.
Il pivot mostra una sezione alla volta, ma in alto possiamo notare la
presenza dei titoli di molteplici sezioni (2 o 3). Questo per
notificare la presenza di ulteriori viste oltre a quella corrente. Il
titolo della sezione attualmente selezionata avrà una colorazione
più marcata e sarà il primo della lista.
La differenza principale con l’Hub, è la presenza di un legame
relativamente forte fra le informazioni contenute nelle singole
pagine. Questo pattern è solitamente utilizzato per mostrare la
stessa tipologia di informazione, ma filtrata o mostrata in maniere
differenti, oppure per mostrare informazioni diverse, ma
comunque legate allo stesso soggetto.
+ Pivot : implementazione
Per inserire un Pivot all’interno della nostra applicazione, è
sufficiente utilizzare il controllo denominato, ovviamente, Pivot. Al
suo interno possiamo inserire le sezioni tramite il controllo
PivotItem. Quest’ultimo possiede una proprietà Header, che
imposteremo per definire il titolo della sezione, mentre per
definire quale sarà il suo contenuto è sufficiente inserire al suo
interno dei controlli XAML.
+ Hub: implementazione
L’utilizzo dell’Hub è lievemente più complicato rispetto al Pivot,
dato che richiede un ulteriore passaggio. Dopo aver inserito il
controllo Hub, è necessario introdurre al suo interno una serie di
HubSection. All’interno di tali nodi non va inserito direttamente il
layout della sezione, ma è necessario inteodurre un ulteriore nodo,
denominato DataTemplate. All’interno di tale nodo inseriremo le
specifiche per la visualizzazione. Per impostare l’immagine è
necessario inserire un Brush all’interno della proprietà
Background.
Fly UP