Technology Experience
.NET World

Layout generale di un’app Windows 8

Sebbene condividano lo stesso approccio, c’è una enorme grande differenza tra costruire un’app per Windows Phone 7 ed un’app per Windows 8. Quest’ultima deve adattarsi alla risoluzione del device su cui sta girando (notebook, ultrabook, tablet, etc.) e soprattutto deve essere in grado di adattarsi a tre modalità di visualizzazione, ovvero:

  • landscape (quando tenete il pc in orizzontale)
  • portrait (quando tenete il pc in verticale)
  • snapped (quando andate ad agganciare l’app sul bordo sinistro o destro dello schermo)

Sappiamo tutti che il modo migliore è lasciare che il runtime .NET o WinRT faccia tutto il lavoro di intercettazione del cambiamento della vista: tramite il Visual State Manager possiamo andare a modificare qualsiasi proprietà della UI per fare in modo che la vista si adatti. In pratica, possiamo, possiamo per esempio rendere visibili/invisibili dei controlli, possiamo stringere/allargare colonne e via dicendo. Questo implica una cosa piuttosto importante: ad ogni controllo su cui vogliamo interagire tramite Visual State Manager dobbiamo assegnare un nome.

Io dal canto mio ho trovato un modo che mi piace di più, riassunto del codice XAML qui sotto.

<Page>
    <Page.Resources>
    </Page.Resources>
    <Grid>
        <”Panel” x:Name="FullScreenMainGrid">
        </”Panel”>
        <Panel x:Name="PortraitMainGrid">
        </”Panel”>
        <Panel x:Name="SnappedMainGrid">
        </”Panel”>
    </Grid>
</Page>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

In pratica avete una Grid esterna che non fa altro che contenere altri tre Panel al suo interno (tali Panel possono essere Canvas, altre Grid, StackPanel, qualsiasi pannello previsto da WinRT – io ho messo Panel giusto per rendere l’idea). In modo alla visualizzazione corrente, solo uno di questi Panel sarà visibile in un dato momento. C’è il Panel che contiene il layout specifico per il landscape, poi c’è quello per il portrait, ed infine c’è quello dedicato alla visualizzazione snapped. Può sembrare una cosa prolissa, eppure io mi trovo bene così. So che toccando una certa porzione di XAML non vado a modificare le altre viste. E se lavorate con MVVM, basta fare binding e siete a posto: il codice del viewmodel che governa la view è sempre lo stesso.

Lo parte di XAML relativa al Visual State Manager è la seguente:

<VisualStateManager.VisualStateGroups>
    <VisualStateGroup x:Name="ApplicationViewStates">

        <VisualState x:Name="FullScreenLandscape">
            <Storyboard>
                <ObjectAnimationUsingKeyFrames
                    Storyboard.TargetName="FullScreenMainGrid"
                    Storyboard.TargetProperty="Visibility">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames
                    Storyboard.TargetName="SnappedMainGrid"
                    Storyboard.TargetProperty="Visibility">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames
                    Storyboard.TargetName="PortraitMainGrid"
                    Storyboard.TargetProperty="Visibility">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </VisualState>

        <VisualState x:Name="Filled">

        </VisualState>

        <VisualState x:Name="FullScreenPortrait">
            <Storyboard>
                <ObjectAnimationUsingKeyFrames
                    Storyboard.TargetName="FullScreenMainGrid"
                    Storyboard.TargetProperty="Visibility">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames
                    Storyboard.TargetName="SnappedMainGrid"
                    Storyboard.TargetProperty="Visibility">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames
                    Storyboard.TargetName="PortraitMainGrid"
                    Storyboard.TargetProperty="Visibility">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </VisualState>

        <VisualState x:Name="Snapped">
            <Storyboard>
                <ObjectAnimationUsingKeyFrames
                    Storyboard.TargetName="FullScreenMainGrid"
                    Storyboard.TargetProperty="Visibility">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames
                    Storyboard.TargetName="SnappedMainGrid"
                    Storyboard.TargetProperty="Visibility">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="Visible"/>
                </ObjectAnimationUsingKeyFrames>
                <ObjectAnimationUsingKeyFrames
                    Storyboard.TargetName="PortraitMainGrid"
                    Storyboard.TargetProperty="Visibility">
                    <DiscreteObjectKeyFrame KeyTime="0" Value="Collapsed"/>
                </ObjectAnimationUsingKeyFrames>
            </Storyboard>
        </VisualState>
    </VisualStateGroup>
</VisualStateManager.VisualStateGroups>

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

Il concetto è molto semplice: per ogni stato (FullScreenLandscape, FullScreenPortrait, Snapped) rendete invisibili due Panel e rendete visibile quello previsto per quello stato.

In questo modo evitate di impazzire assegnando nomi ai controlli qua e là, e siete assolutamente sicuri di come viene renderizzata una vista in un certo stato. Ogni vista è indipendente dalle altre. Prima cercavo di stringere/allargare colonne e righe di una Grid, oppure di rimpicciolire il FontSize delle TextBlock e degli altri controlli, ma finivo sempre per impazzire. Alla fine penso che la strada più lineare, semplice e comoda da gestire sia questa.

Che ne dite?

Send to Kindle

Igor Damiani

La sua passione per l'informatica nasce nella prima metà degli anni '80, quando suo padre acquistò un Texas Instruments TI-99. Da allora ha continuato a seguire l'evoluzione sia hardware che software avvenuta nel corso degli anni. E' un utente, un videogiocatore ed uno sviluppatore software a tempo pieno. Igor ha lavorato e lavora anche oggi con le più moderne tecnologie Microsoft per lo sviluppo di applicazioni: .NET Framework, XAML, Universal Windows Platform, su diverse piattaforme, tra cui spiccano Windows 10 piattaforme mobile. Numerose sono le app che Igor ha creato e pubblicato sul marketplace sotto il nome VivendoByte, suo personale marchio di fabbrica. Adora mantenere i contatti attraverso Twitter e soprattutto attraverso gli eventi delle community .NET.

Un pensiero su “Layout generale di un’app Windows 8

  • Bellissimo!!! stavo girando a vuoto quando ho trovato questa bellissima guida! GRAZIE

    Rispondi

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.