Come abbiamo già introdotto nel precedente articolo, Apps4windows8 è un framework applicativo basato su WinRT, il nuovo runtime introdotto da Windows 8 per costruire applicazioni immersive, destinate a essere pubblicate sul Windows Store.
Una volta creata la nostra prima applicazione, iniziamo a capire le potenzialità di questo framework, analizzandone da vicino il codice sorgente. Per continuare nella lettura di questo articolo, vi consigliamo di esservi assicurati che la vostra prima app sia pronta, come abbiamo già introdotto nell'articolo precedente.
Le parti principali dell'applicazione
L'applicazione generata dal wizard è scritta utilizzando XAML e C# (ma è disponibile anche una versione in HTML+JavaScript), che sono una delle possibili combinazioni attraverso le quali costruire applicazioni per il Windows Store.
L'applicazione è suddivisa in diverse parti, che si occupano di visualizzare i contenuti. Tutte le view fanno uso del binding, che è una caratteristica peculiare di XAML (oltre che uno dei principali vantaggi rispetto ad altre tecnologie), ma, per questioni di semplicità, non sono scritte utilizzando il pattern M-V-VM (Model-View-ViewModel). L'approccio scelto è quello più tradizionale, basato su eventi, così da rendere personalizzabile il codice anche a sviluppatori con una minore dimestichezza con XAML, ma che già conoscano lo sviluppo event-driven, perché abituati ad ASP.NET o WinForms.
Le principali view dell'applicazione sono posizionate nella folder Pages e sono:
Vista | Descrizione |
---|---|
MainPage.xaml | è responsabile del rendering dell'home page, offrendo, attraverso l'AppBar, l'accesso alle sezioni secondarie |
ListPage.xaml | rappresenta la pagina che mostra i dettagli di una data categoria, in modalità lista |
GridPage.xaml | come sopra, ma visualizza i template in griglia |
NewsGridPage.xaml | come i precedenti, ma utilizzando un template che ricorda da vicino quello dell'app News di Windows 8 |
SearchResultPage.xaml | mostra i risultati della ricerca |
ItemDetailPage.xaml | visualizza i dettagli del contenuto, consentendo di aggiungere alla start screen lo stesso, per poterlo ritrovare poi con comodità |
Tutte queste viste vanno ad utilizzare un engine che gestisce il download dei feed ed il loro salvataggio in locale, per poter essere utilizzati anche in off-line. Questo engine è impostato in modo che i feed locali e remoti siano diversificati, ma gestiti in maniera uniforme. In particolare, la definizione dei feed viene fatta all'interno di un file chiamato Autogenerated.cs e posto nella folder Services, all'interno del progetto.
Diamo un'occhiata più approfondita per capire come personalizzare questo aspetto.
La definizione delle sezioni
Il file Services\Autogenerated.cs è generato in automatico durante la fase di configurazione dell'applicazione via web. Questo file definisce i feed che saranno visualizzati dall'applicazione ed è autogenerato dal tool che crea il progetto per la prima volta. A seconda che il feed sia locale o remoto, viene creata un'istanza della classe LocalFeedLoader o di quella RemoteFeedLoader. Di seguito riportiamo un esempio:
public static class Repository
{
// Definiamo le sezioni e le policy di caricamento
private static Dictionary<SectionNames, ILoader> loaders = new Dictionary<SectionNames, ILoader>
{
{SectionNames.LinkUtili,new LocalFeedLoader("Link.xml", IconTypeEnum.Links)},
{SectionNames.Photo,new RemoteFeedLoader(new Uri("http://api.flickr.com/services/feeds/photos_public.gne?tags=Microsof+Surface"), IconTypeEnum.News)},
};
}
Nello snippet precedente abbiamo definito 2 sezioni, una locale e l'altra remota. Oltre ai link ai file statici o remoti, abbiamo definito la tipologia di sezione, attraverso l'enum IconTypeEnum. Questo ci consente di scegliere tra una library di icone predefinite che sono mostrate se all'elemento non viene associata un'immagine. Ecco la lista:
- Links
- Info
- News
- Farmacie
- Orari
- Auto
- Ristoranti
- Sport
- Video
- Cibo
- Lavoro
- Mappe
- Musica
- Cinema
- Giochi
Una volta definite le sezioni, è necessario specificare quali andranno in home e quali nella barra superiore, perché meno importanti:
// definiamo le sezioni visibili nella barra di navigazione
private static Dictionary<SectionNames, Func<Section>> sections =
new Dictionary<SectionNames, Func<Section>>
{
{ SectionNames.LinkUtili,
() => new Section(SectionNames.LinkUtili, "Link utili", SectionTypeEnum.Grid)
},
};
// definiamo le sezioni visibili in home page
private static Dictionary<SectionNames, Func<Section>> homeSections =
new Dictionary<SectionNames, Func<Section>>
{
{ SectionNames.Photo,
() => new Section(SectionNames.Photo, "Photo", SectionTypeEnum.PhotoGallery, LayoutTypeEnum.Grid)
},
};
L'enum SectionTypeEnum
ci consente di definire il tipo di visualizzazione, una volta che entreremo nel dettaglio. Possiamo scegliere tra:
Icona | Nome | Descrizione |
---|---|---|
PhotoGallery | per visualizzare un elenco di fotografie e poi, nel dettaglio, far partire uno slideshow | |
VideoGallery | per visualizzare un elenco di video e poi, nel dettaglio, riprodurne uno alla volta | |
List | mosterà gli elementi in lista, con possibilità di visualizzare subito il dettaglio (stile treeview con dettaglio visualizzato contestualmente) | |
Grid | visualizzazione classica in griglia, con piccola anteprima dei contenuti e navigazione ad una pagina di dettaglio specifica | |
News | i contenuti saranno visualizzati con un look simile a quello dell'app News di Windows 8, con dettaglio visualizzato in maniera differente rispetto alle altre categorie |
Solo per quanto riguarda le sezioni in homepage, è necessario specificare anche un valore per l'enum LayoutTypeEnum, che indica come saranno visualizzati i contenuti in home:
Icona | Nome | Descrizione |
---|---|---|
Classic | visualizzazione classica | |
Grid | visualizzazione in griglia | |
Horizontal | template orizzontale | |
Alternative | un template che alterna in maniera ripetuta il layout |
Una volta scelti i layout per home page ed interno, l'app è pronta ad essere utilizzata. In automatico, verrà gestito il cambio di layout in base alle impostazioni definite dallo sviluppatore.
Come visualizzare i contenuti in dettaglio
Il modo in cui visualizzeremo i contenuti è legato a come creiamo i nostri feed. Sia quelli locali che quelli remoti seguono delle regole semplici. Per prima cosa, per visualizzare l'immagine come anteprima in liste e homepage, è necessario che il feed RSS o ATOM la includano. Tutto il codice è contenuto nel file Pages/ItemDetailPage.xaml/.xaml.cs.
In particolare, per il formato RSS, è necessario includere in ogni elemento
<enclosure length="1" type="image/jpeg" url="http://myurl" />
Il sistema accetta tutti i formati di immagine supportati da Windows e cerca "image/" all'interno dell'attributo type.
I contenuti possono essere veicolati all'interno del feed RSS anche in formato HTML, che poi sarà visualizzato in maniera nativa dall'applicazione, senza perdere la formattazione:
All'interno della pagina di dettaglio, è possibile accedere alle impostazioni dell'applicazione, che sono salvate nel profilo roaming dell'utente. Questo consente alle impostazioni di essere salvate in cloud e sincronizzate tra i diversi device dell'utente.
Le opzioni consentono, in questa release, di impostare la dimensione del carattere nella view di dettaglio:
Questa pagina utilizza una tecnica particolare, che cambia la dimensione del carattere attraverso un JavaScript ad hoc, che cambia al volo la dimensione, facendo mostrare di nuovo la view al controllo WebView.
Per mantenere una formattazione il più simile al template grafico scelto, è presente un template.css all'interno della folder Assets, all'interno del quale vengono definiti gli stili. In generale non è necessario modicarlo, a meno che vogliate aggiungere comportamenti o layout nuovi.
Riguardo al CSS, per supportare le viste immersive (quella che si ha quando la sezione è di tipo News), ci sono delle regole del CSS ad hoc che, usando il supporto ai CSS3 di Internet Explorer 10 (che è quello che il controllo WebView utilizza sotto il cofano), organizza il layout in colonne.
Lo stesso discorso è fatto per la vista snapped, che forza il layout ad una dimensione minore, impostando anche una dimensione massima per le eventuali immagini presenti.
Riguardo ai contenuti, se non viene fornito all'interno del feed RSS (locale o remoto) un contenuto, in automatico viene renderizzata la pagina remota. Per i feed locali che non vogliano puntare a contenuti remoti, è possibile utilizzare come URL qualcosa che inizi per http://local/. In questo modo, non sarà offerto all'utente la possibilità di navigare al dettaglio all'interno dell'AppBar (link Apri in browser):
Tutti i feed statici sono salvati nella folder Resources, dove possono anche essere salvate eventuali immagini. Nell'esempio che segue viene mostrato come far riferimento alle immagini locali e come evitare che l'app mostri il link "Apri in browser":
<?xml version="1.0" encoding="utf-8" ?>
<rss version="2.0">
<channel>
<title>Esempio di feed locale</title>
<description>Esempio di feed locale</description>
<language>it-it</language>
<item>
<title>Contenuto</title>
<enclosure url="http://local/Resources/Images/1.jpg" type="image/jpeg" />
<link>http://local/mycategory/1</link>
<description>
<![CDATA[contenuto in HTML]]>
</description>
</item>
<item>
<title>Contenuto</title>
<enclosure url="http://local/Resources/Images/2.jpg" type="image/jpeg" />
<link>http://local/mycategory/2</link>
<description>
<![CDATA[contenuto in HTML]]>
</description>
</item>
</channel>
</rss>
Questi comportamenti sono particolarmente comodi con feed locali, perché in molti casi non è necessario puntare ad un contenuto remoto per approfondimenti, perché i dati sono tutti disponibili direttamente nell'app.
Infine, un discorso a parte è necessario per le mappe. Possiamo intergrare una mappa all'interno dell'app con un feed come il seguente (locale o remoto):
<item>
<title>Dove si trova il comune</title>
<link>http://www.bing.com/maps/embed/...</link>
<description></description>
<category>map</category>
</item>
In particolare, il tag
Conclusioni
Con questa prima, rapida analisi, abbiamo dato un'occhiata generale a come è strutturata l'applicazione, analizzandone le componenti principali e come queste cooperino per arrivare a creare il risultato finale.
Questo framework è molto flessibile e consente di creare applicazioni che fruiscano di contenuti di qualsiasi natura, sia prelevati da un server remoto, tanto creati ad hoc e distribuiti all'interno dell'applicazione stessa.
Approfondiremo poi, altri aspetti all'interno delle prossime puntate di questa guida.