8 - Layout (StackPanel)


Existen diferentes controles para definir el Layout (disposición) de nuestras aplicaciones universales de Windows. Seguramente cuando una interfaz sea compleja se combinarán distintos controles de layout. El objetivo fundamental de estos controles de Layout es permitir la implementación de interfaces visuales que se puedan ver correctamente en dispositivos con tamaños de pantalla tan disímiles (4,5,7,10,20 etc. pulgadas)

En los ejercicios anteriores solo arrastramos los controles visuales desde el "Cuadro de Herramientas" y los ubicamos con coordenadas absolutas.

Si por ejemplo elegimos para una consola XBox y disponemos un botón cerca del margen inferior derecho:

Layout

Y luego cambiamos la vista a un equipo Surface Book:

Layout

Podemos observar que si bien se puede ver el botón en ambas pantallas no es una solución eficiente para pantallas grandes (desperdiciaremos mucho espacio en pantallas grandes)

Otra cosa importante es que cuando tenemos que implementar interfaces complejas es muy común que codifiquemos directamente en el archivo XAML en lugar de arrastrar los objetos desde el "Cuadro de herramientas". Comenzaremos a partir de este concepto a codificar gran parte de la interfaz de nuestra aplicación directamente en el archivo XAML y dejaremos el "Cuadro de herramientas" y la ventana de "Propiedades" para casos específicos.

Control StackPanel.

El layout StackPanel nos permite disponer un conjunto de componentes visuales uno debajo del otro o uno al lado del otro. Recordemos que stack significa apilar.

Desarrollaremos una interfaz que muestre una pantalla con cinco botones uno debajo del otro y aparezcan centrados en horizontal y vertical.

Como primer paso creamos un nuevo proyecto llamado "Proyecto7" seleccionando desde el menú de opciones del Visual Studio: Archivo -> Nuevo -> Proyecto.

Ahora seleccionamos el archivo MainPage.xaml en el "Explorador de soluciones" y pasamos a codificar en el archivo el siguiente código, es una buena medida que codifique el siguiente código para ver como el editor de texto XAML nos ayuda:

<Page
    x:Class="Proyecto7.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Proyecto7"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel>
        <Button x:Name="boton1" Content="Opción 1" />
        <Button x:Name="boton2" Content="Opcion 2" />
        <Button x:Name="boton3" Content="Opcion 3" />
        <Button x:Name="boton4" Content="Opcion 4" />
        <Button x:Name="boton5" Content="Opcion 5" />
    </StackPanel>
</Page>

Por ahora no modificaremos nada las propiedades que define el elemento raiz "Page":

    x:Class="Proyecto7.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Proyecto7"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

Luego si eliminamos el control Grid que crea el Visual Studio 2019 por defecto y procedemos a definir el elemento StackPanel y en su interior definimos cinco elementos Button:

    <StackPanel>
        <Button x:Name="boton1" Content="Opción 1" />
        <Button x:Name="boton2" Content="Opcion 2" />
        <Button x:Name="boton3" Content="Opcion 3" />
        <Button x:Name="boton4" Content="Opcion 4" />
        <Button x:Name="boton5" Content="Opcion 5" />        
    </StackPanel>

El resultado visual parcial es:

StackPanel

Para hacer que los botones aparezcan centrados en forma horizontal y vertical debemos iniciar las propiedades "HorizontalAlignment" y "VerticalAlignment" con el valor Center:

<Page
    x:Class="Proyecto7.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Proyecto7"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel  HorizontalAlignment="Center" VerticalAlignment="Center">
        <Button x:Name="boton1" Content="Opción 1" />
        <Button x:Name="boton2" Content="Opcion 2" />
        <Button x:Name="boton3" Content="Opcion 3" />
        <Button x:Name="boton4" Content="Opcion 4" />
        <Button x:Name="boton5" Content="Opcion 5" />
    </StackPanel>
</Page>

El resultado visual iniciando las propiedades HorizontalAlignment y VerticalAlignment es:

StackPanel

Por último como única finalidad estética definiremos la propiedad Margin a cada botón para dejar un espacio entre los controles (los márgenes se indican en el orden izquierdo,superior,derecho,abajo):

<Page
    x:Class="Proyecto7.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Proyecto7"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <StackPanel  HorizontalAlignment="Center" VerticalAlignment="Center">
        <Button x:Name="boton1" Content="Opción 1" Margin="0,10,0,10" />
        <Button x:Name="boton2" Content="Opcion 2" Margin="0,10,0,10" />
        <Button x:Name="boton3" Content="Opcion 3" Margin="0,10,0,10" />
        <Button x:Name="boton4" Content="Opcion 4" Margin="0,10,0,10" />
        <Button x:Name="boton5" Content="Opcion 5" Margin="0,10,0,10" />
    </StackPanel>
</Page>

Si ejecutamos nuestra aplicación en una tablet, en una laptop, en una XBox, en un HoloLens etc. el resultado siempre será el mismo (aparecen los cinco botones en forma vertical y con centrado horizontal y vertical)

Este proyecto lo puede descargar en un zip desde este enlace :Proyecto7.zip

Acotaciones

Como vimos cuando utilizamos el control de layout: StackPanel los objetos que disponemos dentro (Button, TextBox, TextBlock etc.) aparecen uno debajo del otro como una pila. Si queremos que los controles se ubiquen uno al lado del otro en forma horizontal solo debemos iniciar la propiedad "Orientation" con el valor "Horizontal":

    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center" Orientation="Horizontal">
        <Button x:Name="boton1" Content="Opción 1" Margin="0,10,0,10"/>
        <Button x:Name="boton2" Content="Opcion 2" Margin="0,10,0,10"/>
        <Button x:Name="boton3" Content="Opcion 3" Margin="0,10,0,10"/>
        <Button x:Name="boton4" Content="Opcion 4" Margin="0,10,0,10"/>
        <Button x:Name="boton5" Content="Opcion 5" Margin="0,10,0,10"/>        
    </StackPanel>

Los botones aparecen uno al lado del otro:

StackPanel

Esto quiere decir que no es necesario iniciar obligatoriamente la propiedad "Orientation" con el valor "Vertical" ya que este es el valor por defecto.

Anidamiento de StackPanel

Una de las fortalezas de los controles para disponer objetos en la interfaz gráfica es que podemos disponer dentro de un StackPanel otro StackPanel (y cuando veamos otros controles de Layout podremos combinarlos)

Desarrollaremos una interfaz que muestre una pantalla con una fila con dos botones, una segunda fila con tres botones y finalmente una tercer fila con dos botones.

Como primer paso creamos un nuevo proyecto llamado "Proyecto8" seleccionando desde el menú de opciones del Visual Studio: Archivo -> Nuevo -> Proyecto.

Ahora seleccionamos el archivo MainPage.xaml en el "Explorador de soluciones" y pasamos a codificar en el archivo el siguiente código:

<Page
    x:Class="Proyecto8.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Proyecto8"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

    <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <Button x:Name="boton1" Content="Opción 1" Margin="10,10,10,10"/>
            <Button x:Name="boton2" Content="Opción 2" Margin="10,10,10,10"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="center">
            <Button x:Name="boton3" Content="Opción 3" Margin="10,10,10,10"/>
            <Button x:Name="boton4" Content="Opción 4" Margin="10,10,10,10"/>
            <Button x:Name="boton5" Content="Opción 5" Margin="10,10,10,10"/>
        </StackPanel>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <Button x:Name="boton6" Content="Opción 6" Margin="10,10,10,10"/>
            <Button x:Name="boton7" Content="Opción 7" Margin="10,10,10,10"/>
        </StackPanel>
    </StackPanel>
</Page>

Tenemos como resultado:

StackPanel

Como vemos definimos un primer StackPanel que iniciamos las propiedades VerticalAlignment="Center" HorizontalAlignment="Center":

    <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center">

    .......

    </StackPanel>

Y dentro de este StackPanel definimos otros tres StackPanel (aparecen cada StackPanel uno debajo del otro) iniciando la propiedad Orientation con el valor "Horizontal" (esto hace que los botones dentro de este StackPanel aparezcan uno al lado del otro) y definiendo varios botones en cada uno:

        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <Button x:Name="boton1" Content="Opción 1" Margin="10,10,10,10"/>
            <Button x:Name="boton2" Content="Opción 2" Margin="10,10,10,10"/>            
        </StackPanel>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="center">
            <Button x:Name="boton3" Content="Opción 3" Margin="10,10,10,10"/>
            <Button x:Name="boton4" Content="Opción 4" Margin="10,10,10,10"/>
            <Button x:Name="boton5" Content="Opción 5" Margin="10,10,10,10"/>            
        </StackPanel>
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
            <Button x:Name="boton6" Content="Opción 6" Margin="10,10,10,10"/>
            <Button x:Name="boton7" Content="Opción 7" Margin="10,10,10,10"/>
        </StackPanel>

Este proyecto lo puede descargar en un zip desde este enlace :Proyecto8.zip

Retornar