Organización de vistas con Grid

Completado

Imagine que va a crear una página en la que se muestran imágenes en una cuadrícula de 7 x 5. Esta página se puede crear con varios contenedores de StackLayout horizontales y verticales. Pero resultaría tedioso de programar y podría provocar problemas de rendimiento debido a los requisitos de memoria y procesamiento de los distintos paneles de diseño. El panel de diseño Grid es una opción mejor para las interfaces de usuario que necesitan filas y columnas. En esta unidad, aprenderá a definir un diseño Grid y ubicar vistas dentro de sus celdas.

¿Qué es Grid?

Grid es un panel de diseño que consta de filas y columnas. En la ilustración siguiente se muestra una vista conceptual de una cuadrícula.

Ilustración en la que se muestra una cuadrícula de ejemplo con filas y columnas de cuadros, con un cuadro que abarca varias filas y columnas.

Las vistas se colocan en las celdas que se crean a partir de la intersección de las filas y las columnas. Por ejemplo, si crea un diseño Grid que tiene tres columnas y dos filas, habrá seis celdas disponibles para las vistas. Las filas y las columnas pueden tener diferentes tamaños, o bien se pueden establecer para que se adapten de forma automática al tamaño de los elementos secundarios que se colocan en su interior. Las vistas secundarias pueden ocupar una sola celda o varias. Esta flexibilidad hace que Grid sea una buena elección como panel de diseño raíz para muchas aplicaciones.

Cómo especificar las filas y columnas de una cuadrícula

Al crear un Grid, puede definir cada fila y columna individualmente. Este sistema proporciona control total sobre el alto de cada fila y el ancho de cada columna. Todos los diseños Grid tienen una colección de objetos RowDefinition y ColumnDefinition que definen la forma de la cuadrícula. Debe rellenar esas colecciones con instancias de RowDefinition y ColumnDefinition, cada una para representar una fila o columna de la interfaz de usuario.

Estos son dos fragmentos de código en los que se muestran las definiciones de clase para RowDefinition y ColumnDefinition:

public sealed class RowDefinition : ...
{
    ...
    public GridLength Height { get; set; }
}
public sealed class ColumnDefinition : ...
{
    ...
    public GridLength Width { get; set; }
}

Observe que RowDefinition tiene una propiedad denominada Height y que ColumnDefinition tiene una propiedad denominada Width. Use estas propiedades para establecer el alto de una fila y el ancho de una columna, como se describe en las secciones siguientes.

¿Qué es GridLength?

El tipo de datos de las propiedades Width y Height es GridLength. Este tipo contiene dos propiedades: GridUnitType y Value. Este es un fragmento de código en el que se muestra una parte de la definición del tipo.

public struct GridLength
{
    ...
    public GridUnitType GridUnitType { get; }
    public double Value { get; }
}

Puede establecer la propiedad GridUnitType en uno de estos valores:

  • Absolute
  • Auto
  • Star

Cada uno de estos valores se examinará con más detalle.

Absolute GridUnitType

Absolute especifica que la fila o la columna tienen un tamaño fijo. Puede usar la propiedad Value para indicar el tamaño. Este es un ejemplo en el que se muestra cómo establecer el alto de una fila en un tamaño fijo de 100 unidades de dispositivo en C#. Observe cómo se podría usar el constructor de GridLength, que toma un valor numérico. Este constructor establece GridUnitType en Absolute de forma automática.

var row = new RowDefinition() { Height = new GridLength(100) };

En el lenguaje XAML, solo tiene que proporcionar un valor numérico. El analizador XAML invoca un convertidor de tipos para crear la instancia de GridLength. En este ejemplo se muestra lo mismo en XAML:

<RowDefinition Height="100" />

Auto GridUnitType

Auto cambia automáticamente el tamaño de la fila o la columna para ajustarlo a las vistas secundarias. Grid examina todas las vistas secundarias de esa fila o columna, selecciona la de mayor tamaño y, después, hace que la fila o la columna sea lo suficientemente grande para ajustarse a ese elemento secundario. Cuando se crea una definición de fila en el código, se omite el valor numérico. Se puede usar cualquier valor. En este ejemplo se muestra cómo se establecería el alto de una fila con ajuste de tamaño automático en C#. Observe que se ha elegido arbitrariamente 1 para el valor.

var row = new RowDefinition() { Height = new GridLength(1, GridUnitType.Auto) };

En XAML, se usa el valor Auto. En este ejemplo se muestra lo mismo en XAML.

<RowDefinition Height="Auto" />

Star GridUnitType

Star ofrece un ajuste de tamaño proporcional. En el dimensionamiento proporcional, el tamaño se determina por el espacio total disponible y la relación que solicita cada fila o columna. En lenguaje coloquial, esto se suele denominar variación de tamaño proporcional en lugar de dimensionamiento proporcional.

Se analizará el proceso del uso de la variación de tamaño proporcional para las filas de una cuadrícula.

  1. Determine el espacio disponible: Grid examina todas las filas en las que Grid se usa la variación de tamaño proporcional. Suma el alto de todas esas filas y resta ese total del alto del propio diseño Grid. Este cálculo proporciona la cantidad de espacio disponible para todas las filas con variación de tamaño proporcional.

  2. Divida el espacio disponible: Después, Grid divide el espacio disponible entre todas las filas con variación de tamaño proporcional según el valor Value de cada fila. La propiedad Value se puede considerar un multiplicador que determina la proporción entre todas las filas definidas con variación de tamaño proporcional. Por ejemplo, si tuviera dos filas con variación de tamaño proporcional, las dos con 1 como multiplicador, el espacio disponible se dividiría de forma equitativa entre las dos. Pero si una de ellas tuviera 2 como el valor, obtendría el doble de espacio que la otra.

En este ejemplo se muestra cómo se establecería el alto de una fila para ser 2 Star en C#:

var row = new RowDefinition() { Height = new GridLength(2, GridUnitType.Star) };

En XAML, para representar la variación de tamaño proporcional se usa el símbolo *. El valor y el signo * se combinan en una sola cadena y un convertidor de tipos crea GridLength de forma automática. Este es el mismo ejemplo en XAML.

<RowDefinition Height="2*" />

Colecciones de cuadrícula

Después de definir las filas y columnas mediante RowDefinition y ColumnDefinition, puede agregarlas a un Grid. Use las propiedades RowDefinitions y ColumnDefinitions de colección de la Grid. Rellenar estas colecciones se realiza habitualmente en XAML.

En este ejemplo se muestra cómo definir cuatro filas y agregarlas a un diseño Grid mediante la propiedad RowDefinitions:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="100" />
        <RowDefinition Height="Auto" />
        <RowDefinition Height="1*" />
        <RowDefinition Height="2*" />
    </Grid.RowDefinitions>
    ...
</Grid>

Esta definición se puede acortar a:

<Grid RowDefinitions="100, Auto, 1*, 2*">
    ...
</Grid>

El XAML para definir columnas es análogo al XAML anterior. Excepto que usaría ColumnDefinitions y establecería Width.

En tiempo de ejecución, este código XAML generará un diseño Grid con cuatro filas. La primera fila tiene una altura fija de 100 unidades de dispositivo. La segunda fila tiene la altura de la vista más alta de la fila. En la tercera y cuarta filas se usa la variación de tamaño proporcional, lo que significa que toman el espacio disponible restante y lo dividen proporcionalmente en función de su multiplicador Value. Como la tercera fila es 1* y la cuarta es 2*, la cuarta duplica la altura de la tercera.

Tamaño predeterminado de filas y columnas

El valor predeterminado para las filas y columnas es el tamaño 1*. Por ejemplo, vea el siguiente código XAML.

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition />
        <RowDefinition />
        <RowDefinition />
    </Grid.RowDefinitions>
    <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
    </Grid.ColumnDefinitions>
    ...
</Grid>

Esta definición se puede acortar a:

<Grid RowDefinitions="*, *, *" ColumnDefinitions="*, *">
    ...
</Grid>

Como en ninguna de las filas o columnas se ha especificado un tamaño, se aplica 1* a todas ellas. En el entorno de ejecución, esta configuración crea un diseño Grid uniforme, lo que significa que todas las filas tienen el mismo alto y todas las columnas el mismo ancho.

Cómo agregar vistas a una cuadrícula

Cuando se agrega una vista a un Grid, se agrega a una celda concreta. Las celdas se crean en las posiciones de intersección de las filas y columnas. Para colocar una vista en una celda, es necesario conocer la ubicación de la celda. Para identificar una celda se usa una combinación de un número de fila y un número de columna.

Numeración de filas y columnas

La numeración de filas y columnas comienza en cero. El origen es la esquina superior izquierda. En esta ilustración se muestra la numeración de un diseño Grid con cuatro filas y dos columnas.

Ilustración que muestra una cuadrícula con cuatro filas y dos columnas. La numeración se muestra para cada fila y columna. A partir del cuadro superior izquierdo en la columna cero y cero de la fila, hasta el cuadro inferior derecho de la columna 1 y la fila 3.

Por ejemplo, si quisiera agregar una vista a la celda inferior derecha, diría que la posición de la vista es row 3 column 1.

Adición de una vista a una cuadrícula mediante propiedades adjuntas

Se necesita una manera de especificar el número de columna y de fila de una vista cuando se agrega a una cuadrícula. Una solución sería definir las propiedades Row y Column en la clase base View para poder especificar la posición directamente en la vista. Esta técnica podría funcionar, pero no es el enfoque más eficaz. Las vistas no son siempre van a estar en un diseño Grid, por lo que en ocasiones esas propiedades no serán necesarias. Un mejor enfoque consiste en usar propiedades adjuntas.

Una propiedad adjunta es la que se define en una clase, pero se establece en objetos de otros tipos.

Imagine que las propiedades adjuntas son como una colección de pares clave-valor que forman parte de una vista. Cuando agrega una vista a una Grid, especifica la fila y la columna. Mediante las propiedades adjuntas, se puede agregar un par clave-valor con la clave Grid.Row, y un valor que indica el número de la fila. Cuando el diseño Grid está listo para colocar la vista, comprueba la colección para ver si hay una clave denominada Grid.Row. Si existe, Grid usa el valor para colocar la vista.

En este ejemplo se muestra cómo crear un diseño Grid y agregar una vista mediante propiedades adjuntas:

<Grid RowDefinitions="*, *, *" ColumnDefinitions="*, *">

    <BoxView Grid.Row="1" Grid.Column="0" Color="Navy" />
    
</Grid>

Como puede ver, Grid.Row=1 y Grid.Column=0 son pares clave-valor que se agregan a una colección interna del BoxView. Grid usa esos valores para determinar dónde se debe colocar la vista. Este diseño Grid tendría el aspecto siguiente si la aplicación se ejecutara en un dispositivo.

Ilustración en la que se muestra una cuadrícula con tres filas y dos columnas. Se muestra un objeto BoxView en la segunda fila de la primera columna.

Cómo hacer que una vista abarque varias filas o columnas

Hay dos propiedades adjuntas más que debe tener en cuenta: Grid.RowSpan y Grid.ColumnSpan. Estas propiedades especifican cuántas filas o columnas debe ocupar la vista. Por ejemplo, vea el siguiente código XAML.

<Grid RowDefinitions="*, *, *" ColumnDefinitions="*, *">

    <BoxView Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" Color="Navy" />
    
</Grid>

Observe que este ejemplo establece el valor ColumnSpan en 2. Esta vista ocupará dos columnas a partir de Column 0. Este diseño Grid tendría el aspecto siguiente si la aplicación se ejecutara en un dispositivo.

Ilustración en la que se muestra una cuadrícula con tres filas y dos columnas. Un objeto BoxView se ubica en la segunda fila de la primera columna y abarca ambas columnas.

Comprobación de conocimiento

1.

¿Cuál es el objetivo del Star GridUnitType?