Compartir a través de


Xamarin.Forms Cuadrícula

Xamarin.Forms Cuadrícula

El Grid es un diseño que organiza sus elementos secundarios en filas y columnas, que pueden tener tamaños proporcionales o absolutos. De forma predeterminada, las vistas Grid contienen una fila y una columna. Además, se puede usar una Grid como diseño primario que contiene otros diseños secundarios.

El diseño Grid no debe confundirse con las tablas y no está pensado para presentar datos tabulares. A diferencia de las tablas HTML, una Grid está pensada para diseñar contenido. Para mostrar datos tabulares, considere el uso de un elemento ListView, CollectionView o TableView.

La clase Grid define las propiedades siguientes:

  • Column, de tipo int, que es una propiedad adjunta que indica la alineación de columna de una vista dentro de un elemento primario Grid. El valor predeterminado de esta propiedad es 0. Una devolución de llamada de validación garantiza que, cuando se establece la propiedad, su valor es mayor o igual que 0.
  • ColumnDefinitions, de tipo ColumnDefinitionCollection, es una lista de objetos ColumnDefinition que definen el ancho de las columnas de cuadrícula.
  • ColumnSpacing, de tipo double, indica la distancia entre las columnas de cuadrícula. El valor predeterminado de esta propiedad es 6 unidades independientes del dispositivo.
  • ColumnSpan, de tipo int, que es una propiedad adjunta que indica el número total de columnas que abarca una vista dentro de un elemento primario Grid. El valor predeterminado de esta propiedad es 1. Una devolución de llamada de validación garantiza que, cuando se establece la propiedad, su valor es mayor o igual que 1.
  • Row, de tipo int, que es una propiedad adjunta que indica la alineación de fila de una vista dentro de un elemento primario Grid. El valor predeterminado de esta propiedad es 0. Una devolución de llamada de validación garantiza que, cuando se establece la propiedad, su valor es mayor o igual que 0.
  • RowDefinitions, de tipo RowDefinitionCollection, es una lista de RowDefintion objetos que definen el alto de las filas de cuadrícula.
  • RowSpacing, de tipo double, indica la distancia entre las filas de cuadrícula. El valor predeterminado de esta propiedad es 6 unidades independientes del dispositivo.
  • RowSpan, de tipo int, que es una propiedad adjunta que indica el número total de filas que abarca una vista dentro de un elemento primario Grid. El valor predeterminado de esta propiedad es 1. Una devolución de llamada de validación garantiza que, cuando se establece la propiedad, su valor es mayor o igual que 1.

Todas estas propiedades están respaldadas por objetos BindableProperty, lo que significa que las propiedades pueden ser destinos de los enlaces de datos, y se les puede aplicar estilos.

La clase Grid deriva de la clase Layout<T>, que define una propiedad Children de tipo IList<T>. La propiedad Children es ContentProperty de la clase Layout<T> y, por tanto, no es necesario establecerla explícitamente desde XAML.

Sugerencia

Para obtener el mejor rendimiento posible del diseño, siga las instrucciones de Optimización del rendimiento del diseño.

En filas y columnas

De forma predeterminada, un Grid contiene una fila y una columna:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="GridTutorial.MainPage">
    <Grid Margin="20,35,20,20">
        <Label Text="By default, a Grid contains one row and one column." />
    </Grid>
</ContentPage>

En este ejemplo, el Grid contiene un único elemento secundario Label que se coloca automáticamente en una única ubicación:

Captura de pantalla de un diseño de cuadrícula predeterminado

El comportamiento de diseño de un Grid se puede definir con las propiedades RowDefinitions y ColumnDefinitions, que son colecciones de objetos RowDefinition y ColumnDefinition, respectivamente. Estas colecciones definen las características de fila y columna de un Grid y deben contener un objeto RowDefinition para cada fila del Gridy un objeto ColumnDefinition para cada columna de Grid.

La clase RowDefinition define una propiedad Height, de tipo GridLengthy la clase ColumnDefinition define una propiedad Width de tipo GridLength. La estructura GridLength especifica un alto de fila o un ancho de columna en términos de la enumeración GridUnitType, que tiene tres miembros:

  • Absolute: el ancho o el alto se especifica en unidades independientes del dispositivo (un número en XAML).
  • Auto: el alto de la fila o el ancho de la columna se ajusta automáticamente según el contenido de la celda (Auto en XAML).
  • Star: el alto de fila o el ancho de columna izquierda se asignan proporcionalmente (un número seguido de * en XAML).

Una fila Grid con una Height propiedad de Auto restringe el alto de las vistas de esa fila de la misma manera que una vertical StackLayout. De forma similar, una columna con una Width propiedad de Auto funciona de forma muy similar a una horizontal StackLayout.

Precaución

Intenta asegurarte de establecer en tamaño Auto el menor número posible de filas y columnas. Cada fila o columna de tamaño automático hará que el motor de diseño tenga que realizar cálculos de diseño adicionales. En su lugar, use filas y columnas de tamaño fijo si es posible. Como alternativa, establece las filas y columnas para ocupar una cantidad proporcional de espacio con el valor de enumeración GridUnitType.Star.

En el código XAML siguiente se muestra cómo crear un Grid objeto con tres filas y dos columnas:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="GridDemos.Views.BasicGridPage"
             Title="Basic Grid demo">
   <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="2*" />
            <RowDefinition Height="*" />
            <RowDefinition Height="100" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>
        ...
    </Grid>
</ContentPage>

En este ejemplo, el Grid tiene un alto general que es el alto de la página. Las Grid saben que el alto de la tercera fila es de 100 unidades independientes del dispositivo. Resta esa altura de su propia altura y asigna la altura restante proporcionalmente entre las primeras y las segundas filas en función del número anterior a la estrella. En este ejemplo, el alto de la primera fila es el doble del de la segunda fila.

Los dos objetos ColumnDefinition establecen el valor de Width en *, que es el mismo que 1*, lo que significa que el ancho de la pantalla se divide equitativamente debajo de las dos columnas.

Importante

El valor predeterminado de la propiedad RowDefinition.Height es *. De forma similar, el valor predeterminado de la propiedad ColumnDefinition.Width es *. Por lo tanto, no es necesario establecer estas propiedades en los casos en los que estos valores predeterminados son aceptables.

Las vistas secundarias se pueden colocar en celdas Grid específicas con las propiedades adjuntas Grid.Column y Grid.Row. Además, para que las vistas secundarias abarquen varias filas y columnas, usa las propiedades Grid.RowSpan y Grid.ColumnSpan adjuntas.

El siguiente XAML muestra la misma definición Grid y también coloca las vistas secundarias en celdas Grid específicas:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="GridDemos.Views.BasicGridPage"
             Title="Basic Grid demo">
   <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="2*" />
            <RowDefinition />
            <RowDefinition Height="100" />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <BoxView Color="Green" />
        <Label Text="Row 0, Column 0"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
        <BoxView Grid.Column="1"
                 Color="Blue" />
        <Label Grid.Column="1"
               Text="Row 0, Column 1"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
        <BoxView Grid.Row="1"
                 Color="Teal" />
        <Label Grid.Row="1"
               Text="Row 1, Column 0"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
        <BoxView Grid.Row="1"
                 Grid.Column="1"
                 Color="Purple" />
        <Label Grid.Row="1"
               Grid.Column="1"
               Text="Row1, Column 1"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
        <BoxView Grid.Row="2"
                 Grid.ColumnSpan="2"
                 Color="Red" />
        <Label Grid.Row="2"
               Grid.ColumnSpan="2"
               Text="Row 2, Columns 0 and 1"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
    </Grid>
</ContentPage>

Nota:

Las propiedades Grid.Row y Grid.Column se indexan desde 0, por lo que Grid.Row="2" hace referencia a la tercera fila mientras Grid.Column="1" hace referencia a la segunda columna. Además, ambas propiedades tienen un valor predeterminado de 0, por lo que no es necesario establecer en vistas secundarias que ocupan la primera fila o la primera columna de un Grid.

En este ejemplo, las tres filas Grid están ocupadas por las vistas BoxView y Label. La tercera fila es de un alto de 100 unidades independientes del dispositivo, y las dos primeras filas ocupan el espacio restante (la primera fila es el doble de alta que la segunda). Las dos columnas son iguales de ancho y dividen el valor de Grid por la mitad. El BoxView de la tercera fila abarca ambas columnas.

Captura de pantalla de un diseño de cuadrícula básico

Además, las vistas secundarias de un Grid pueden compartir celdas. El orden en que aparecen los elementos secundarios en el XAML es el orden en que se colocan los elementos secundarios en Grid. En el ejemplo anterior, los objetos Label solo son visibles porque se representan sobre los objetos BoxView. Los objetos Label no serían visibles si los objetos BoxView se representasen encima de ellos.

El código de C# equivalente es el siguiente:

public class BasicGridPageCS : ContentPage
{
    public BasicGridPageCS()
    {
        Grid grid = new Grid
        {
            RowDefinitions =
            {
                new RowDefinition { Height = new GridLength(2, GridUnitType.Star) },
                new RowDefinition(),
                new RowDefinition { Height = new GridLength(100) }
            },
            ColumnDefinitions =
            {
                new ColumnDefinition(),
                new ColumnDefinition()
            }
        };

        // Row 0
        // The BoxView and Label are in row 0 and column 0, and so only needs to be added to the
        // Grid.Children collection to get default row and column settings.
        grid.Children.Add(new BoxView
        {
            Color = Color.Green
        });
        grid.Children.Add(new Label
        {
            Text = "Row 0, Column 0",
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center
        });

        // This BoxView and Label are in row 0 and column 1, which are specified as arguments
        // to the Add method.
        grid.Children.Add(new BoxView
        {
            Color = Color.Blue
        }, 1, 0);
        grid.Children.Add(new Label
        {
            Text = "Row 0, Column 1",
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center
        }, 1, 0);

        // Row 1
        // This BoxView and Label are in row 1 and column 0, which are specified as arguments
        // to the Add method overload.
        grid.Children.Add(new BoxView
        {
            Color = Color.Teal
        }, 0, 1, 1, 2);
        grid.Children.Add(new Label
        {
            Text = "Row 1, Column 0",
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center
        }, 0, 1, 1, 2); // These arguments indicate that that the child element goes in the column starting at 0 but ending before 1.
                        // They also indicate that the child element goes in the row starting at 1 but ending before 2.

        grid.Children.Add(new BoxView
        {
            Color = Color.Purple
        }, 1, 2, 1, 2);
        grid.Children.Add(new Label
        {
            Text = "Row1, Column 1",
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center
        }, 1, 2, 1, 2);

        // Row 2
        // Alternatively, the BoxView and Label can be positioned in cells with the Grid.SetRow
        // and Grid.SetColumn methods.
        BoxView boxView = new BoxView { Color = Color.Red };
        Grid.SetRow(boxView, 2);
        Grid.SetColumnSpan(boxView, 2);
        Label label = new Label
        {
            Text = "Row 2, Column 0 and 1",
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center
        };
        Grid.SetRow(label, 2);
        Grid.SetColumnSpan(label, 2);

        grid.Children.Add(boxView);
        grid.Children.Add(label);

        Title = "Basic Grid demo";
        Content = grid;
    }
}

En el código, para especificar el alto de un objeto RowDefinition y el ancho de un objeto ColumnDefinition, se usan valores de la estructura GridLength, a menudo en combinación con la enumeración GridUnitType.

El código de ejemplo anterior también muestra varios enfoques diferentes para agregar elementos secundarios a la Grid y especificar las celdas en las que residen. Al usar la sobrecarga Add que especifica izquierda, derecha, superior y argumentos de inferior, mientras que los argumentos izquierdo y superior siempre harán referencia a celdas dentro de la Grid, los argumentos derecho e inferior hacen referencia a las celdas que están fuera del Grid. Esto se debe a que el argumento derecho debe ser siempre mayor que el argumento izquierdo y el argumento inferior siempre debe ser mayor que el argumento superior. En el ejemplo siguiente, que supone un 2x2 de Grid, se muestra código equivalente con las dos sobrecargas de Add:

// left, top
grid.Children.Add(topLeft, 0, 0);           // first column, first row
grid.Children.Add(topRight, 1, 0);          // second column, first tow
grid.Children.Add(bottomLeft, 0, 1);        // first column, second row
grid.Children.Add(bottomRight, 1, 1);       // second column, second row

// left, right, top, bottom
grid.Children.Add(topLeft, 0, 1, 0, 1);     // first column, first row
grid.Children.Add(topRight, 1, 2, 0, 1);    // second column, first tow
grid.Children.Add(bottomLeft, 0, 1, 1, 2);  // first column, second row
grid.Children.Add(bottomRight, 1, 2, 1, 2); // second column, second row

Nota:

Además, las vistas secundarias se pueden agregar a un Grid con los métodos AddHorizontal y AddVertical, que agregan elementos secundarios a una sola fila o columna única Grid. A continuación, el Grid se expande en filas o columnas a medida que se realizan estas llamadas, así como colocación automática de elementos secundarios en las celdas correctas.

Simplificar definiciones de filas y columnas

En XAML, las características de fila y columna de Grid se pueden especificar mediante una sintaxis simplificada que evita tener que definir objetos RowDefinition y ColumnDefinition para cada fila y columna. En su lugar, las propiedades RowDefinitions y ColumnDefinitions se pueden establecer en cadenas que contienen valores de GridUnitType delimitados por comas, desde los que los convertidores de tipos integrados en Xamarin.Forms crean objetos RowDefinition y ColumnDefinition:

<Grid RowDefinitions="1*, Auto, 25, 14, 20"
      ColumnDefinitions="*, 2*, Auto, 300">
    ...
</Grid>

En este ejemplo, Grid tiene cinco filas y cuatro columnas. La tercera, la cuarta y la quinta fila se establecen en alturas absolutas, con el tamaño automático de la segunda fila ajustado al contenido. Después, el alto restante se asigna a la primera fila.

La columna cuarta se establece en un ancho absoluto, con el tamaño automático de la tercera columna ajustado al contenido. El ancho restante se asigna proporcionalmente entre las columnas primera y segunda basándose en el número anterior a la estrella. En este ejemplo, el ancho de la segunda columna es dos veces el de la primera columna (porque el valor * es idéntico al valor 1*).

Espacio entre filas y columnas

De forma predeterminada, filas de Grid están separadas por 6 unidades de espacio independientes del dispositivo. Del mismo modo, columnas de Grid están separadas por 6 unidades de espacio independientes del dispositivo. Estos valores predeterminados se pueden cambiar estableciendo las propiedades RowSpacing y ColumnSpacing, respectivamente:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="GridDemos.Views.GridSpacingPage"
             Title="Grid spacing demo">
    <Grid RowSpacing="0"
          ColumnSpacing="0">
        ..
    </Grid>
</ContentPage>

En este ejemplo se crea un Grid que no tiene espaciado entre sus filas y columnas:

Captura de pantalla de cuadrícula sin espaciado entre celdas

Sugerencia

Las propiedades RowSpacing y ColumnSpacing se pueden establecer en valores negativos para que el contenido de la celda se superponga.

El código de C# equivalente es el siguiente:

public GridSpacingPageCS()
{
    Grid grid = new Grid
    {
        RowSpacing = 0,
        ColumnSpacing = 0,
        // ...
    };
    // ...

    Content = grid;
}

Alineación

Las vistas secundarias de un elemento Grid se pueden colocar dentro de sus celdas mediante las propiedades HorizontalOptions y VerticalOptions. Estas propiedades se pueden establecer en los siguientes campos de la estructura LayoutOptions:

Importante

Los campos AndExpands de la estructura de LayoutOptions solo se aplican a los objetos StackLayout.

El siguiente XAML crea un Grid con nueve celdas del mismo tamaño y coloca un elemento Label en cada celda con una alineación diferente:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="GridDemos.Views.GridAlignmentPage"
             Title="Grid alignment demo">
    <Grid RowSpacing="0"
          ColumnSpacing="0">
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <BoxView Color="AliceBlue" />
        <Label Text="Upper left"
               HorizontalOptions="Start"
               VerticalOptions="Start" />
        <BoxView Grid.Column="1"
                 Color="LightSkyBlue" />
        <Label Grid.Column="1"
               Text="Upper center"
               HorizontalOptions="Center"
               VerticalOptions="Start"/>
        <BoxView Grid.Column="2"
                 Color="CadetBlue" />
        <Label Grid.Column="2"
               Text="Upper right"
               HorizontalOptions="End"
               VerticalOptions="Start" />
        <BoxView Grid.Row="1"
                 Color="CornflowerBlue" />
        <Label Grid.Row="1"
               Text="Center left"
               HorizontalOptions="Start"
               VerticalOptions="Center" />
        <BoxView Grid.Row="1"
                 Grid.Column="1"
                 Color="DodgerBlue" />
        <Label Grid.Row="1"
               Grid.Column="1"
               Text="Center center"
               HorizontalOptions="Center"
               VerticalOptions="Center" />
        <BoxView Grid.Row="1"
                 Grid.Column="2"
                 Color="DarkSlateBlue" />
        <Label Grid.Row="1"
               Grid.Column="2"
               Text="Center right"
               HorizontalOptions="End"
               VerticalOptions="Center" />
        <BoxView Grid.Row="2"
                 Color="SteelBlue" />
        <Label Grid.Row="2"
               Text="Lower left"
               HorizontalOptions="Start"
               VerticalOptions="End" />
        <BoxView Grid.Row="2"
                 Grid.Column="1"
                 Color="LightBlue" />
        <Label Grid.Row="2"
               Grid.Column="1"
               Text="Lower center"
               HorizontalOptions="Center"
               VerticalOptions="End" />
        <BoxView Grid.Row="2"
                 Grid.Column="2"
                 Color="BlueViolet" />
        <Label Grid.Row="2"
               Grid.Column="2"
               Text="Lower right"
               HorizontalOptions="End"
               VerticalOptions="End" />
    </Grid>
</ContentPage>

En este ejemplo, los objetos Label de cada fila están alineados verticalmente de forma idéntica, pero usan diferentes alineaciones horizontales. Como alternativa, esto se puede considerar como los objetos Label de cada columna que se alinean de forma idéntica horizontal, pero con diferentes alineaciones verticales:

Captura de pantalla de la alineación de celdas dentro de una cuadrícula

El código de C# equivalente es el siguiente:

public class GridAlignmentPageCS : ContentPage
{
    public GridAlignmentPageCS()
    {
        Grid grid = new Grid
        {
            RowSpacing = 0,
            ColumnSpacing = 0,
            RowDefinitions =
            {
                new RowDefinition(),
                new RowDefinition(),
                new RowDefinition()
            },
            ColumnDefinitions =
            {
                new ColumnDefinition(),
                new ColumnDefinition(),
                new ColumnDefinition()
            }
        };

        // Row 0
        grid.Children.Add(new BoxView
        {
            Color = Color.AliceBlue
        });
        grid.Children.Add(new Label
        {
            Text = "Upper left",
            HorizontalOptions = LayoutOptions.Start,
            VerticalOptions = LayoutOptions.Start
        });

        grid.Children.Add(new BoxView
        {
            Color = Color.LightSkyBlue
        }, 1, 0);
        grid.Children.Add(new Label
        {
            Text = "Upper center",
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Start
        }, 1, 0);

        grid.Children.Add(new BoxView
        {
            Color = Color.CadetBlue
        }, 2, 0);
        grid.Children.Add(new Label
        {
            Text = "Upper right",
            HorizontalOptions = LayoutOptions.End,
            VerticalOptions = LayoutOptions.Start
        }, 2, 0);

        // Row 1
        grid.Children.Add(new BoxView
        {
            Color = Color.CornflowerBlue
        }, 0, 1);
        grid.Children.Add(new Label
        {
            Text = "Center left",
            HorizontalOptions = LayoutOptions.Start,
            VerticalOptions = LayoutOptions.Center
        }, 0, 1);

        grid.Children.Add(new BoxView
        {
            Color = Color.DodgerBlue
        }, 1, 1);
        grid.Children.Add(new Label
        {
            Text = "Center center",
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.Center
        }, 1, 1);

        grid.Children.Add(new BoxView
        {
            Color = Color.DarkSlateBlue
        }, 2, 1);
        grid.Children.Add(new Label
        {
            Text = "Center right",
            HorizontalOptions = LayoutOptions.End,
            VerticalOptions = LayoutOptions.Center
        }, 2, 1);

        // Row 2
        grid.Children.Add(new BoxView
        {
            Color = Color.SteelBlue
        }, 0, 2);
        grid.Children.Add(new Label
        {
            Text = "Lower left",
            HorizontalOptions = LayoutOptions.Start,
            VerticalOptions = LayoutOptions.End
        }, 0, 2);

        grid.Children.Add(new BoxView
        {
            Color = Color.LightBlue
        }, 1, 2);
        grid.Children.Add(new Label
        {
            Text = "Lower center",
            HorizontalOptions = LayoutOptions.Center,
            VerticalOptions = LayoutOptions.End
        }, 1, 2);

        grid.Children.Add(new BoxView
        {
            Color = Color.BlueViolet
        }, 2, 2);
        grid.Children.Add(new Label
        {
            Text = "Lower right",
            HorizontalOptions = LayoutOptions.End,
            VerticalOptions = LayoutOptions.End
        }, 2, 2);

        Title = "Grid alignment demo";
        Content = grid;
    }
}

Objetos Grid anidados

Grid se puede usar como diseño primario que contiene objetos secundarios anidados Grid u otros diseños secundarios. Al anidar Grid objetos, las propiedades adjuntas Grid.Row, Grid.Column, Grid.RowSpan, y Grid.ColumnSpan siempre hacen referencia a la posición de las vistas dentro de su elemento primario Grid.

En el siguiente ejemplo de XAML se muestra una clase para objetos Grid:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:converters="clr-namespace:GridDemos.Converters"
             x:Class="GridDemos.Views.ColorSlidersGridPage"
             Title="Nested Grids demo">

    <ContentPage.Resources>
        <converters:DoubleToIntConverter x:Key="doubleToInt" />

        <Style TargetType="Label">
            <Setter Property="HorizontalTextAlignment"
                    Value="Center" />
        </Style>
    </ContentPage.Resources>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <BoxView x:Name="boxView"
                 Color="Black" />
        <Grid Grid.Row="1"
              Margin="20">
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>
            <Slider x:Name="redSlider"
                    ValueChanged="OnSliderValueChanged" />
            <Label Grid.Row="1"
                   Text="{Binding Source={x:Reference redSlider},
                                  Path=Value,
                                  Converter={StaticResource doubleToInt},
                                  ConverterParameter=255,
                                  StringFormat='Red = {0}'}" />
            <Slider x:Name="greenSlider"
                    Grid.Row="2"
                    ValueChanged="OnSliderValueChanged" />
            <Label Grid.Row="3"
                   Text="{Binding Source={x:Reference greenSlider},
                                  Path=Value,
                                  Converter={StaticResource doubleToInt},
                                  ConverterParameter=255,
                                  StringFormat='Green = {0}'}" />
            <Slider x:Name="blueSlider"
                    Grid.Row="4"
                    ValueChanged="OnSliderValueChanged" />
            <Label Grid.Row="5"
                   Text="{Binding Source={x:Reference blueSlider},
                                  Path=Value,
                                  Converter={StaticResource doubleToInt},
                                  ConverterParameter=255,
                                  StringFormat='Blue = {0}'}" />
        </Grid>
    </Grid>
</ContentPage>

En este ejemplo, el diseño de la raíz Grid contiene un BoxView en su primera fila y un Grid secundario en su segunda fila. El elemento secundario Grid contiene Slider objetos que manipulan el color mostrado por los objetos BoxView, y Label que muestran el valor de cada Slider:

Captura de pantalla de cuadrículas anidadas

Importante

Cuanto más profundo anides Grid los objetos y otros diseños, más afectarán al rendimiento. Para obtener más información, consulta Elegir el diseño correcto.

El código de C# equivalente es el siguiente:

public class ColorSlidersGridPageCS : ContentPage
{
    BoxView boxView;
    Slider redSlider;
    Slider greenSlider;
    Slider blueSlider;

    public ColorSlidersGridPageCS()
    {
        // Create an implicit style for the Labels
        Style labelStyle = new Style(typeof(Label))
        {
            Setters =
            {
                new Setter { Property = Label.HorizontalTextAlignmentProperty, Value = TextAlignment.Center }
            }
        };
        Resources.Add(labelStyle);

        // Root page layout
        Grid rootGrid = new Grid
        {
            RowDefinitions =
            {
                new RowDefinition(),
                new RowDefinition()
            }
        };

        boxView = new BoxView { Color = Color.Black };
        rootGrid.Children.Add(boxView);

        // Child page layout
        Grid childGrid = new Grid
        {
            Margin = new Thickness(20),
            RowDefinitions =
            {
                new RowDefinition(),
                new RowDefinition(),
                new RowDefinition(),
                new RowDefinition(),
                new RowDefinition(),
                new RowDefinition()
            }
        };

        DoubleToIntConverter doubleToInt = new DoubleToIntConverter();

        redSlider = new Slider();
        redSlider.ValueChanged += OnSliderValueChanged;
        childGrid.Children.Add(redSlider);

        Label redLabel = new Label();
        redLabel.SetBinding(Label.TextProperty, new Binding("Value", converter: doubleToInt, converterParameter: "255", stringFormat: "Red = {0}", source: redSlider));
        Grid.SetRow(redLabel, 1);
        childGrid.Children.Add(redLabel);

        greenSlider = new Slider();
        greenSlider.ValueChanged += OnSliderValueChanged;
        Grid.SetRow(greenSlider, 2);
        childGrid.Children.Add(greenSlider);

        Label greenLabel = new Label();
        greenLabel.SetBinding(Label.TextProperty, new Binding("Value", converter: doubleToInt, converterParameter: "255", stringFormat: "Green = {0}", source: greenSlider));
        Grid.SetRow(greenLabel, 3);
        childGrid.Children.Add(greenLabel);

        blueSlider = new Slider();
        blueSlider.ValueChanged += OnSliderValueChanged;
        Grid.SetRow(blueSlider, 4);
        childGrid.Children.Add(blueSlider);

        Label blueLabel = new Label();
        blueLabel.SetBinding(Label.TextProperty, new Binding("Value", converter: doubleToInt, converterParameter: "255", stringFormat: "Blue = {0}", source: blueSlider));
        Grid.SetRow(blueLabel, 5);
        childGrid.Children.Add(blueLabel);

        // Place the child Grid in the root Grid
        rootGrid.Children.Add(childGrid, 0, 1);

        Title = "Nested Grids demo";
        Content = rootGrid;
    }

    void OnSliderValueChanged(object sender, ValueChangedEventArgs e)
    {
        boxView.Color = new Color(redSlider.Value, greenSlider.Value, blueSlider.Value);
    }
}