Tutorial MVVM V

En este quinto artículo sobre MVVM, después de haber montado el Modelo en los anteriores post, y unas pruebas unitarias asociadas al Modelo, vamos a crear la vista, la cual va a estar formada a partir de 3 componentes, aunque todo podría estar en el mismo componente, es más práctico y funcional que esté separado en distintos controles, ya que así nos permite la reutilización de elementos en otros, y es que una de las ventajas más importantes de WPF, es la potencia del marcado XAML, que nos deja introducir controles que contienen a otros que a su vez pueden contener a otros distintos.

En la solución, tenemos un proyecto de WPF, si no es así lo creamos, y lo establecemos como proyecto principal de la compilación. Por defecto, vendrá un control MainWindow.xaml que será la ventana principal de la aplicación. Agregamos un nuevo control de usuario, y en el marcado de este control, al objeto Grid, le agregamos dos filas, en la primera insertamos un StackPanel con orientación vertical, que contenga un TextBox con un ancho mínimo de 200px y un Button alineado a la derecha. En la segunda fila agregamos un objeto ListBox el cual albergará los resultados de la búsqueda que hagamos, que serán las localizaciones que coincidan con el texto del TextBox. Y nos queda algo así:

<UserControl x:Class="WeatherApp.Components.Search"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             mc:Ignorable="d" 
             d:DesignHeight="300" d:DesignWidth="300">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition />
        </Grid.RowDefinitions>
        <StackPanel Grid.Row="0" Orientation="Vertical" Margin="5">
            <TextBox MinWidth="200"/>
            <Button Content="Buscar" HorizontalAlignment="Right"/>
        </StackPanel>
        <ListBox Grid.Row="1" Margin="5"></ListBox>
    </Grid>
</UserControl>

A continuación agregamos un control tipo Page, este objeto se puede utilizar para integrarlo en un Frame, el cual trae de serie la gestión de una pila de páginas navegadas, y los controles de navegación para poder ir atrás o hacía adelante. La página estará compuesta por un Grid de dos columnas, la primera que se autoajuste y la segunda que se ajuste el ancho al contenido, en la primera agregamos un objeto Image, que de momento no configuramos su Source, y en la segunda agregamos un StackPanel en el que los objetos se orienten verticalmente, y que su alineación vertical sea también en el centro, este panel contiene a su vez dos TextBlock que albergarán la temperatura y el nombre de la ciudad. Por último agregamos un objeto Border con un ColSpan y orientado arriba a la derecha, con dos RadioButton los cuales permitirán el cambio entre grados Farenheit y Celsius.

<Page x:Class="WeatherApp.Components.Weather"
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
      mc:Ignorable="d"
      d:DesignHeight="300" d:DesignWidth="300"
    Title="Weather">
 
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition/>
            <ColumnDefinition Width="Auto"/>
        </Grid.ColumnDefinitions>
        <Image Grid.Column="0" Stretch="Uniform" VerticalAlignment="Center"/>
        <StackPanel VerticalAlignment="Center" Orientation="Vertical">
            <TextBlock FontSize="36" FontWeight="Bold"/>
            <TextBlock FontSize="18" FontWeight="Bold"/>
        </StackPanel>
        <Border Grid.ColumnSpan="2" CornerRadius="5" VerticalAlignment="Top"
                HorizontalAlignment="Right" Margin="3">
            <StackPanel Orientation="Horizontal">
                <RadioButton GroupName="Degree">Fº</RadioButton>
                <RadioButton GroupName="Degree">Cº</RadioButton>
            </StackPanel>
        </Border>
    </Grid>
</Page>

Seguido, introducimos en el MainWindow un objeto Frame, y a continuación un objeto Expander, que se expande hacía a la izquierda, y lo ubicamos alineado a la derecha, en el Header introducimos un TextBlock con el texto «Búsqueda» y rotado 90 grados, y en el Content el componente de búsqueda que hemos creado antes.

<Window x:Class="WeatherApp.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:comp="clr-namespace:WeatherApp.Components"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Frame />
        <Expander ExpandDirection="Left" HorizontalAlignment="Right">
            <Expander.Header>
                <TextBlock Text="Búsqueda" >
                    <TextBlock.LayoutTransform>
                        <TransformGroup>
                            <ScaleTransform/>
                            <SkewTransform/>
                            <RotateTransform Angle="90"/>
                            <TranslateTransform/>
                        </TransformGroup>
                    </TextBlock.LayoutTransform>
                </TextBlock>
            </Expander.Header>
            <comp:Search />
        </Expander>
    </Grid>
</Window>

En el siguiente post, continuaremos elaborando el ViewModel de cada uno de estos objetos, y los relacionaremos para después continuar haciendo los Binding a las propiedades.