Contenedores.

Los contenedores son aquellos controles que establecen la disposición espacial de los controles que contienen. Por lo tanto, un contenedor vacío no tiene sentido; siempre debe contener (como su propio nombre indica) algún control en su interior.

Ya hemos visto el contenedor 'Grid' un poco en los ejemplos anteriores. Volveremos a él detalladamente más adelante. Antes vamos a ver otros controles contenedores.

Contenedor 'Canvas'.

Es un contenedor poco usado, aunque bien es verdad que tiene cierta funcionalidad muy peculiar que ningún otro control puede satisfacer. Define un área en la que pueden colocarse sus elementos secundarios haciendo uso de un sistema de coordenadas relativas del área del contenedor. Veamos un ejemplo:

<Canvas Background="LightBlue">
    <Label Canvas.Left="80" Canvas.Top="30" Content="etiqueta"/>
    <Button Canvas.Left="80" Canvas.Top="60" Content="botón"/>
</Canvas>

Ejecuta la aplicación y prueba a modificar la posición de los controles. Te recomiendo también que, puesto que ya conoces varios controles, experimentes con otros diferentes de los que salen enn los ejemplos, modificando sus propiedades y contenidos.

Contenedor 'StackPanel'.

Es uno de los contenedores más útiles. Sus elementos secundarios son apilados vertical u horizontalmente en el orden en el que son escritos en el código fuente. Su propiedad fundamental es 'Orientation', en la que estableceremos el modo vertical u horizontal.

<StackPanel Orientation"Vertical">
    <Label Content="etiqueta"/>
    <Button Content="botón"/>
</StackPanel>

Los contenedores 'StackPanel' pueden estar anidados. Por ejemplo: un contenedor 'StackPanel' vertical que contiene una etiqueta y otro contenedor 'StackPanel' horizontal, que a su vez contiene dos etiquetas. Prueba a realizar esta contrucción sin mi ayuda, ya que es importante que controles bien este contenedor que, como ya te he dicho, es uno de los contenedores más útiles y también más usados.

Contenedor 'WrapPanel'.

Muy útil en casos en los que es necesario mantener un máximo de ancho de un conjunto de controles para no sobrepasar las dimensiones de una ventana o pantalla. Los elementos secundarios se sitúan por orden de izquierda a derecha y, cuando oel espacio se ha acabado, continúan situándose en una línea siguiente por debajo.

<WrapPanel>
    <Label Content="etiqueta"/>
    <Button Content="botón 1"/>
    <Button Content="botón 2"/>
    <Button Content="botón 3"/>
    <Button Content="botón 4"/>
    <Button Content="botón 5"/>
    <Button Content="botón 6"/>
    <Button Content="botón 7"/>
    <Button Content="botón 8"/>
    <Button Content="botón 9"/>
    <Button Content="botón 10"/>
</StackPanel>

Prueba a ejecutar este código modificando el tamaño de la ventana para comprobar el ajuste izquierda-derecha/arriba-abajo de los controles en el momento que el conjunto de ellos sobrepasa las dimensiones de la ventana.

Contenedor 'DockPanel'.

Los elementos secundarios quedan alineados con los borders del mismo, siendo la alineación por defecto hacia la izquierda. Este contenedor puede causar problemas cuando no estamos acostumbrados a su uso, pero no te preocupes si al principio no sabes sacarle todo su rendimiento, es cuestión de experiencia. Prueba con el siguiente código XAML:

<DockPanel>
    <Border DockPanel.Dock="Top" BorderBrush="Silver" BorderThickness="2" Height="25">
        <TextBlock Text="Barra de menú"/>
    </Border>
    <Border DockPanel.Dock="Top" BorderBrush="Silver" BorderThickness="2" Height="25">
        <TextBlock Text="Barra de herramientas"/>
    </Border>
    <Border DockPanel.Dock="Bottom" BorderBrush="Silver" BorderThickness="2" Height="25">
        <TextBlock Text="Barra de estado"/>
    </Border>
    <Border DockPanel.Dock="Left" BorderBrush="Silver" BorderThickness="2" Width="85">
        <TextBlock Text="Columna izquierda"/>
    </Border>
    <Border BorderBrush="Silver" BorderThickness="2" Height="25">
        <TextBlock Text="Columna derecha"/>
    </Border>
</DockPanel>

Ahora sí que te recomiendo de verdad que experimentes modificando este código para comprobar el resultado én la colocación de los elementos en la ventana. Comprobarás que también es importante el orden en el que escribes en el código fuente cada uno de los elementos integrados en el contenedor. Con el tiempo conseguirás práctica con este contenedor y descubrirás que es el contenedor perfecto para usarlo como contenedor principal de una ventana.

Contenedor 'Grid'.

Este contenedor es el más usado en las aplicaciones WPF. Define un área de cuadríaculas flexibles compuesta por filas y columnas establecidas por el programador. Estas filas y columnas, además de que podamos establecerlas a nuestra voluntad, pueden ser establecidas con unas dimensiones determinadas, o bien puede indicarse que sus dimensiones se ajusten al tamaño total de las dimensiones que ocupan sus elementos secundarios. Veamos un ejemplo, antes del cual deberás añadir al proyecto una imagen cualquiera en formato '.ico':

<Grid ShowGridLines="True">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="Auto">
        <ColumnDefinition Width="2*">
        <ColumnDefinition Width="*">
        <ColumnDefinition Width="*">
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto">
        <RowDefinition Height="Auto">
        <RowDefinition Height="*">
        <RowDefinition Height="Auto">
    </Grid.RowDefinitions>
    <Image Grid.Row="0" Grid.Column="0" Source="libro.ico"/>
    <TextBlock Padding="10,3,10,3" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" TextWrapping="Wrap" Text="Escriba el nombre del documento:"/>
    <TextBlock Grid.Row="1" Grid.Column="0" Text="Abrir:"/>
    <TextBox Grid.Row="1" Grid.Column="1" Grid.ColumnSpan="3"/>
    <Button Margin="10,1,10,15" Grid.Row="3" Grid.Column="2" Content="Aceptar"/>
    <Button Margin="10,1,10,15" Grid.Row="3" Grid.Column="3" Content="Cancelar"/>
</Grid>

Al indicar como '*' el alto de una fila o el ancho de una columna, esa fila o columna recibe una proporción ponderada del espacio restante disponible. Por ejemplo, la fila o la columna '2*' recibe el espacio disponible el doble que la fila o columna con un simple '*'. Por el contrario, 'Auto' distribuye el espacio de manera uniforma basándose en el tamaño del contenido que está dentro de una fila o columna.

Hemos aprovechado a incluir el control 'Image' en este código XAML. Como habrás comprobado, el valor de su propiedad 'Source' hace referencia a la ruta relativa en la que se encuentra situado el archivo 'libro.ico'. Podríamos haber incluido el archivo de imagen en una carpeta de imágenes llamada, por ejemplo, 'images', según lo cual el valor de la propiedad 'Source' debería haber sido 'images/libro.ico'.