Disporre le visualizzazioni con Grid
Supponiamo di voler creare una pagina che visualizzi le immagini in una griglia 7 x 5. È possibile creare questa pagina con più contenitori StackLayout
orizzontali e verticali. Tuttavia, compilare il codice sarebbe un'operazione noiosa che potrebbe provocare problemi di prestazioni a causa dei requisiti di memoria ed elaborazione di più pannelli di layout. Il pannello di layout Grid
è una scelta migliore per le interfacce utente che necessitano sia di righe che di colonne. In questa unità si apprende come definire un layout Grid
e posizionare le visualizzazioni all'interno delle relative celle.
Che cos'è una Grid?
Grid
è un pannello di layout costituito da righe e colonne. La figura seguente mostra una visualizzazione concettuale di una griglia.
Le visualizzazioni vengono inserite nelle celle create dall'intersezione tra le righe e le colonne. Ad esempio, se si crea un layout Grid
costituito da tre colonne e due righe, sono disponibili sei celle per le visualizzazioni. Le righe e le colonne possono avere dimensioni diverse oppure possono essere impostate in modo da adattarsi automaticamente alle dimensioni degli elementi figlio posizionati al loro interno. Le visualizzazioni figlio possono occupare una sola cella o estendersi su più celle. Questa flessibilità fa di Grid
una buona scelta per il pannello di layout radice di molte app.
Come specificare le righe e le colonne di una griglia
Quando si crea un oggetto Grid
, è possibile definire ogni riga e colonna singolarmente. Questo sistema offre controllo completo sull'altezza di ogni riga e la larghezza di ogni colonna. Ogni Grid
dispone di una raccolta di oggetti RowDefinition
e ColumnDefinition
che definiscono la forma della griglia. L'utente popola queste raccolte con istanze di RowDefinition
e ColumnDefinition
, ognuna delle quali rappresenta una riga o una colonna nell'interfaccia utente.
Ecco due frammenti di codice che mostrano le definizioni di classe per RowDefinition
e ColumnDefinition
:
public sealed class RowDefinition : ...
{
...
public GridLength Height { get; set; }
}
public sealed class ColumnDefinition : ...
{
...
public GridLength Width { get; set; }
}
Si noti che RowDefinition
ha una proprietà denominata Height
e ColumnDefinition
ha una proprietà denominata Width
. Usare queste proprietà per impostare l'altezza di una riga e la larghezza di una colonna, come descritto nelle sezioni seguenti.
Che cos'è GridLength?
Il tipo di dati per le proprietà Width
e Height
è GridLength
. Questo tipo contiene due proprietà: GridUnitType
e Value
. Ecco un frammento di codice che mostra una parte della definizione del tipo.
public struct GridLength
{
...
public GridUnitType GridUnitType { get; }
public double Value { get; }
}
È possibile impostare la proprietà GridUnitType
su uno di questi valori:
Absolute
Auto
Star
Esaminiamo in maggiore dettaglio ognuno di questi valori.
GridUnitType Absolute
Absolute
specifica che le dimensioni della riga o della colonna devono essere fisse. Utilizzare la proprietà Value
per indicare le dimensioni. Ecco un esempio che illustra come impostare l'altezza di una riga su una dimensione fissa di 100
unità dispositivo in C#. Si osservi come deve essere usato il costruttore GridLength
, che accetta un valore numerico. Questo costruttore imposta automaticamente GridUnitType
su Absolute
.
var row = new RowDefinition() { Height = new GridLength(100) };
In XAML (Extensible Application Markup Language) è sufficiente fornire un valore numerico. Il parser XAML richiama un convertitore di tipi per creare l'istanza GridLength
. Ecco un esempio che illustra la stessa operazione in XAML:
<RowDefinition Height="100" />
GridUnitType Auto
Auto
ridimensiona automaticamente la riga o la colonna per adattarla alle viste figlio. Grid
analizza tutte le viste figlio in tale riga o colonna, seleziona la vista più grande e quindi aumenta le dimensioni della riga o della colonna quanto basta per contenere quella vista. Quando si crea una definizione di riga nel codice, il valore numerico viene ignorato. È possibile usare qualsiasi valore. Ecco un esempio che illustra come impostare l'altezza di una riga in modo che venga ridimensionata automaticamente in C#. Si noti che è stato arbitrariamente scelto 1
come valore.
var row = new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) };
In XAML si usa il valore Auto
. Ecco un esempio che illustra la stessa operazione in XAML.
<RowDefinition Height="Auto" />
GridUnitType Star
Star
consente il ridimensionamento proporzionale. Nel dimensionamento proporzionale, le dimensioni sono determinate dallo spazio totale disponibile e dalla proporzione richiesta da ogni riga o colonna. Nelle conversazioni si parla spesso di ridimensionamento proporzionale (Star) invece che di ridimensionamento proporzionale.
Vediamo nel dettaglio il processo di ridimensionamento proporzionale delle righe in una griglia.
Determinare lo spazio disponibile:
Grid
analizza tutte le righe che non usano il ridimensionamento proporzionale (Star). Somma l'altezza di tutte queste righe e sottrae il totale dall'altezza delGrid
stesso. Questo calcolo fornisce la quantità di spazio disponibile per tutte le righe con ridimensionamento proporzionale (Star).Dividere lo spazio disponibile:
Grid
divide quindi lo spazio disponibile tra tutte le righe con ridimensionamento proporzionale (Star) in base all'impostazioneValue
di ogni riga. La proprietàValue
può essere considerata come un moltiplicatore che determina il rapporto fra tutte le righe a cui è applicato il ridimensionamento proporzionale (Star). Ad esempio, se avessimo due righe con ridimensionamento proporzionale (Star), entrambe con1
come moltiplicatore, lo spazio disponibile verrebbe diviso equamente tra di esse. Se invece una delle righe avesse2
come valore, otterrebbe il doppio dello spazio dell'altra riga.
Ecco un esempio che illustra come impostare l'altezza di una riga su 2 Star
in C#:
var row = new RowDefinition() { Height = new GridLength(2, GridUnitType.Star) };
In XAML si usa il simbolo *
per rappresentare il ridimensionamento proporzionale (Star). Dopo aver unito il valore e il simbolo *
in una singola stringa, un convertitore di tipi crea GridLength
automaticamente. Ecco lo stesso esempio in XAML.
<RowDefinition Height="2*" />
Raccolte di Grid
Dopo aver definito le righe e le colonne usando RowDefinition
e ColumnDefinition
, è possibile aggiungerle a Grid
. Usare le proprietà della raccolta RowDefinitions
e ColumnDefinitions
di Grid
. Il popolamento di queste raccolte avviene in genere in XAML.
Questo esempio illustra come definire quattro righe e aggiungerle a una Grid
usando la proprietà RowDefinitions
:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="Auto" />
<RowDefinition Height="1*" />
<RowDefinition Height="2*" />
</Grid.RowDefinitions>
...
</Grid>
Questa definizione può essere abbreviata in:
<Grid RowDefinitions="100, Auto, 1*, 2*">
...
</Grid>
Il codice XAML per la definizione delle colonne è analogo al codice XAML precedente, ad eccezione del fatto che viene usato ColumnDefinitions
e impostato Width
.
In fase di esecuzione, questo codice XAML produce una Grid
con quattro righe. La prima riga ha un'altezza fissa di 100
unità dispositivo. La seconda riga ha l'altezza corrispondente alla vista più alta nella riga. La terza e la quarta riga usano il ridimensionamento proporzionale, il che significa che lo spazio disponibile rimanente viene diviso in modo proporzionale in base al relativo moltiplicatore Value
. Poiché il valore della terza riga è 1*
e quello della quarta è 2*
, la quarta riga è alta il doppio della terza riga.
Dimensioni predefinite di righe e colonne
Il valore predefinito per le dimensioni di righe e colonne è 1*
. Ad esempio, osservare il codice XAML seguente:
<Grid>
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
<RowDefinition />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition />
</Grid.ColumnDefinitions>
...
</Grid>
Questa definizione può essere abbreviata in:
<Grid RowDefinitions="*, *, *" ColumnDefinitions="*, *">
...
</Grid>
Poiché non sono specificate dimensioni per nessuna delle righe o delle colonne, il valore 1*
viene applicato a tutte. In fase di esecuzione, questa configurazione crea una Grid
uniforme, con tutte le righe della stessa altezza e tutte le colonne della stessa larghezza.
Come aggiungere visualizzazioni a una griglia
Quando si aggiunge una visualizzazione a un oggetto Grid
, la si aggiunge a una cella specifica. Le celle vengono create in corrispondenza delle posizioni di intersezione tra righe e colonne. Per posizionare una visualizzazione in una cella, è necessario conoscere la posizione della cella. Per identificare una cella si usa una combinazione di numero di riga e numero di colonna.
Numerazione di righe e colonne
La numerazione delle righe e delle colonne inizia da zero. L'origine è l'angolo superiore sinistro. L'illustrazione seguente mostra la numerazione di una Grid
con quattro righe e due colonne.
Se, ad esempio, si vuole aggiungere una visualizzazione nella cella inferiore destra, indicare la posizione della visualizzazione come row 3 column 1
.
Aggiungere una visualizzazione a una griglia con le proprietà associate
Serve un modo per specificare il numero di colonna e di riga di una visualizzazione quando la si aggiunge a una griglia. Una soluzione è quella di definire le proprietà Row
e Column
nella classe di base View
in modo da poter specificare la posizione direttamente nella visualizzazione. Questa tecnica funziona, ma non è l'approccio più efficiente. Le visualizzazioni non vengono sempre inserite in una Grid
, quindi a volte queste proprietà non sono necessarie. Un approccio migliore consiste nell'usare le proprietà associate.
Una proprietà associata è una proprietà definita in una classe ma impostata su oggetti di altri tipi.
Una proprietà associata può essere paragonata a una raccolta di coppie chiave-valore che fa parte di una visualizzazione. Quando si aggiunge una visualizzazione a un oggetto Grid
, è necessario specificare la riga e la colonna. Usando le proprietà associate, è possibile aggiungere una coppia chiave-valore con la chiave Grid.Row
e un valore che specifica il numero di riga. Quando la Grid
è pronta per posizionare la vista, verifica se nella raccolta è presente una chiave denominata Grid.Row
. Se è presente, la Grid
usa il valore per posizionare la vista.
Questo esempio illustra come creare una Grid
e aggiungere una visualizzazione usando le proprietà associate:
<Grid RowDefinitions="*, *, *" ColumnDefinitions="*, *">
<BoxView Grid.Row="1" Grid.Column="0" Color="Navy" />
</Grid>
In questo esempio Grid.Row=1
e Grid.Column=0
sono coppie chiave-valore che vengono aggiunte a una raccolta interna di BoxView
. La Grid
usa questi valori per determinare dove deve essere posizionata la vista. Ecco l'aspetto che avrebbe questa Grid
se si eseguisse l'applicazione in un dispositivo.
Come impostare una visualizzazione in modo che si estenda su più righe o colonne
Esistono altre due proprietà associate che è opportuno conoscere: Grid.RowSpan
e Grid.ColumnSpan
. Queste proprietà specificano il numero di righe o colonne che devono essere occupate dalla visualizzazione. Ad esempio, osservare il codice XAML seguente:
<Grid RowDefinitions="*, *, *" ColumnDefinitions="*, *">
<BoxView Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Color="Navy" />
</Grid>
Si noti che questo esempio imposta ColumnSpan
su 2
. Questa vista occupa due colonne a partire da Column 0
. Ecco l'aspetto che avrebbe questa Grid
se si eseguisse l'applicazione in un dispositivo.