Introducción a WPF, y creación de una aplicación WPF 3-D, parte 2 de N.

 

Vale, qué tal a todos, en el post anterior empezamos a ver las maravillas de WPF, al crear un proyecto WPF nuevo, y al empezar a explicar el código en él contenido. Esta vez, veremos primeramente qué es XAML.

Creando una interfaz con XAML

XAML es la manera recomendada para crear interfaces de usuario en el modelo de programación de Windows Presentation Foundation, porque nos proporciona un método para separar la definición del diseño de la IU y la lógica. También permite integrar código usando archivos code-behind.

Con XAML también es posible crear una IU entera sin utilizar código. Esto lo demostramos a continuación. Recordáis el código de la vez anterior, pues aquí he agregado algún código mas:

<Window x:Class=»Window2″
    xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
    xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
    Title=»Window1″ Height=»300″ Width=»300″>
    <Grid>
        <Button Height=»100″ Width=»200″>
            Hola, soy un botón
        </Button>

    </Grid>
</Window>

 

Vale, pues el texto seleccionado es el que hemos insertado a nuestro código. Como véis, es un elemento del tipo botón, ahora bien, cabe resaltar que WPF tiene controles predefinidos, los cuales iremos usando a través de la creación de nuestra aplicación.

Entonces, el elemento Button, es el encargado de crear un nuevo botón dentro de nuestra grilla, como véis, las etiquetas de Button están dentro de las etiquetas Grid. Esto quiere decir que tenemos una estructura jerárquica, donde algunos elementos (casi siempre contenedores) son los que tienen como «hijos» a los demás elementos.

En este caso, de igual forma a Button se le ha definido un Height de 100 y un width de 200, que son los atributos propiamente del botón. Ahora bien, dentro del butón, tenemos el texto «Hola, soy un botón, lo cual quiere decir  que es el contenido del botón, pero no solamente puede ser texto, hubieramos podido insertar cualquier otra cosa, pero de eso hablaremos mas adelante. Por lo pronto, el resultado es el siguiente:

btn1

Vale, ahora procedamos a hacer algo un poco mas complejo, recordáis que les he dicho que una grilla es un contenedor? vale, pues también hemos mencionado que el botón soporta 1 solo elemento contenido(si, el que aparece entre <button>CONTENIDO</button>, asi que en teoría, podemos insertar una grilla como contenido del control, para después, insertar mucho mas contenido dentro del mismísmo botón!! Insertemos una grilla con el siguiente código:

<Window x:Class=»Window2″
    xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
    xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
    Title=»Window1″ Height=»300″ Width=»300″>
    <Grid>
        <Button>
            <Grid>             
            </Grid>
        </Button>
    </Grid>
</Window>

Como véis, hemos en primer lugar, quitado los ATRIBUTOS del botón, asi lograremos que el botón se ajuste a las dimensiones del elemento padre, es decir, de la grilla que lo está conteniendo, que a su vez, se está ajustando a las dimensiones de la ventana(window), y en segundo lugar, hemos reemplazado el contenido de CONTENT que era «Hola soy un botón» por una grilla, a la cual le modificaremos algunos atributos, como véis en el siguiente código:

<Window x:Class=»Window2″
    xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
    xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
    Title=»Window1″ Height=»300″ Width=»300″>
    <Grid>
        <Button>
           <Grid Height=»250″ Width=»250″ HorizontalAlignment=»Center»>             
            </Grid>
        </Button>
    </Grid>
</Window>

A este código solo le hemos cambiado el height y el width, aparte de un nuevo atributo: HorizontalAlignment, el cual nos dice hacia donde queremos ubicar el control en cuestión de su padre, en este caso en el centro.

El resultado es el siguiente:

grilla1

Vale, en la imagen se nota un cuadrado dentro del botón gris, esta es la grilla, pero pasemos a hacer algo mas interesante, insertaremos un video, una imágen y un textblock dentro del mismismo botón, para eso, expliquemos que son las rowsdefinitions y las columndefinitions:

RowDefinition: Dentro de la grilla, marca definiciones de una fila.

ColumnDefinition:Dentro de la grilla, marca definiciones de una columna.

Es decir, cuando aplicamos estas row y column definitions, lo que hacemos es crear como líneas a través de la grilla, con el propósito de guiarnos y de tener una mejor distribucion de los elementos dentro de una grilla. Esto lo ves en el siguiente código:

<Window x:Class=»Window2″
    xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
    xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
    Title=»Window1″ Height=»300″ Width=»300″>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width=»142*» />
            <ColumnDefinition Width=»136*» />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height=»131*» />
            <RowDefinition Height=»131*» />
        </Grid.RowDefinitions>
        <Button Grid.RowSpan=»2″ Grid.ColumnSpan=»2″>
            <Grid Height=»250″ Width=»250″ HorizontalAlignment=»Center»>             
            </Grid>
        </Button>
    </Grid>
</Window>

como ves, las column y row definitions se definen dentro del elemento <Grid></Grid>. Esto es porque pasa a ser un subelemento de Grid, aquí hemos definido 2 column y 2 row definitions. Meramente, las dimensiones mostradas son las de los espacios que hay ocupan cada uno de las definiciones de columna o de filas. El resultado es el siguiente:

grilla2

Como véis, el mismo visual studio nos muestra las respectivas dimensiones de los espacios, de las columnas 142, y 136, y de las filas 131 para cada una.

Ahora bien, para poder insertar apropiadamente el video primeramente, debemos añadirlo dando click derecho a nuestro poyecto, luego Add, y finalmente Existing Item:

exitem

Vale, ahora seleccionamos cualquier video que tengamos, preferentemente uno corto, como lo son los de prueba de Windows, en mi caso insertare el clásico de bear.wmv

sexplorer

Bien, ahora pasemos a agregar un control <MediaElement>

<Window x:Class=»Window2″
    xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
    xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
    Title=»Window1″ Height=»300″ Width=»300″>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width=»142*» />
            <ColumnDefinition Width=»136*» />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height=»131*» />
            <RowDefinition Height=»131*» />
        </Grid.RowDefinitions>
        <Button Grid.RowSpan=»2″ Grid.ColumnSpan=»2″>
            <Grid Height=»250″ Width=»250″ HorizontalAlignment=»Center»>
                <MediaElement Source=»Bear.wmv» Grid.Column=»0″ HorizontalAlignment=»Center» VerticalAlignment=»Top»/>
            </Grid>
        </Button>
    </Grid>
</Window>

Mas que nada, Media Element nos sirve para alojar contenido sobre todo de videos y de música. En este caso, hemos ajustado el alineamiento horizontal lal centro y el alineamiento vertial en «Top», es decir que se ajuste a la parte superior de quien lo contiene.

Bien, si vemos gráficamente esto, el resultado es:

media1

Ahora, si procedemos a ejeuctar esto, ocurre lo siguiente: No se reproduce ningún video. ¿Porqué ocurre esto? Pues porque no tenemos definida ninguna línea de tiempo que reproduzca este video. Sobre esto hablaremos después, por lo pronto, debemos insertar el siguiente código para que el video se reproduzca correctamente:

<Window x:Class=»Window2″
    xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
    xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
    Title=»Window1″ Height=»300″ Width=»300″ xmlns:d=»http://schemas.microsoft.com/expression/blend/2008″ xmlns:mc=»http://schemas.openxmlformats.org/markup-compatibility/2006″ mc:Ignorable=»d»>
   <Window.Resources>
        <Storyboard x:Key=»Bear_wmv»>
            <MediaTimeline BeginTime=»00:00:00″ Storyboard.TargetName=»Bear_wmv» Source=»Bear.wmv»/>
        </Storyboard>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent=»FrameworkElement.Loaded»>
            <BeginStoryboard Storyboard=»{StaticResource Bear_wmv}»/>
        </EventTrigger>
    </Window.Triggers>
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width=»142*» />
            <ColumnDefinition Width=»136*» />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height=»131*» />
            <RowDefinition Height=»131*» />
        </Grid.RowDefinitions>
        <Button Grid.RowSpan=»2″ Grid.ColumnSpan=»2″>
            <Grid Height=»250″ Width=»250″ HorizontalAlignment=»Center»>
            <Grid.ColumnDefinitions>
            <ColumnDefinition Width=»142*» />
            <ColumnDefinition Width=»136*» />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition Height=»131*» />
            <RowDefinition Height=»131*» />
        </Grid.RowDefinitions>
                <MediaElement x:Name=»Bear_wmv» Grid.Row=»0″  Grid.Column=»0″ VerticalAlignment=»Top» Height=»123.5″ Grid.ColumnSpan=»2″ Margin=»0,0,8,0″ />
        </Grid>
        </Button>
    </Grid>
</Window>

Vale, lo mas sobresaliente de este código, es que hemos creado una línea del tiempo (<Storyboard>), la cual dice:

<Storyboard x:Key=»Bear_wmv»> = Etiqueta de tipo linea del tiempo, con un nombre (o llave de key) que se llamará Bear_wmv

<MediaTimeline BeginTime=»00:00:00″ Storyboard.TargetName=»Bear_wmv» Source=»Bear.wmv»/> = Línea del tiempo del tipo media, con el tiempo de inicio 00:00:00 ( o sea que empiece a reproducir a partir de ese tiempo en el video), un objetivo que va a ser Bear_wmv, que es como hemos definido el MediaElement dentro de nuestra grilla, y con la fuente u orígen que será Bear.wmv propiamente.

Si os dáis cuenta, hemos quitado el Source del mediaelement dentro de la grilla dentro del botón, esto es debido a que será la la MediaTimeline quien apunte directamente al Mediaelement de nuestro botón.

Luego vienen los cierres de etiquetas.

Notad que esto se encuentra definido dentro de <Windows.Resources>, lo cual nos dice que se crearán recursos que estarán disponibles para usarlos cuando queramos y donde queramos en el programa.

Luego, se especifica lo siguente:

<Window.Triggers> = Son lanzadores del programa, o sea que se ejcutarán cuando cierta reacción se realicen en el programa .
        <EventTrigger RoutedEvent=»FrameworkElement.Loaded»> = en este caso, cuando nuestro programa sea cargado.
            <BeginStoryboard Storyboard=»{StaticResource Bear_wmv}»/> = Iniciará el storyboard llamado Bear_wmv, que es recurso estático
        </EventTrigger> = cierre de etiquetas
    </Window.Triggers> = cierre de etiquetas
El resultado es el siguiente:

boton2

Como veis, un vídeo reproduciéndose dentro de un botón!!

Ahora, lo que tenemos que hacer es agregar una imagen a nuestro proyecto, con click derecho sobre nuestro proyecto, agregar elemento existene. Agrega cualquier imagen.

Ahora, tenemos que referenciarla por medio de código, esto lo hacemos así:

<Window x:Class=»Window2″
    xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
    xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
    Title=»Window1″ Height=»300″ Width=»300″ xmlns:d=»http://schemas.microsoft.com/expression/blend/2008″ xmlns:mc=»http://schemas.openxmlformats.org/markup-compatibility/2006″ mc:Ignorable=»d»>
    <Window.Resources>
        <Storyboard x:Key=»Bear_wmv»>
            <MediaTimeline BeginTime=»00:00:00″ Storyboard.TargetName=»Bear_wmv» Source=»Bear.wmv»/>
        </Storyboard>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent=»FrameworkElement.Loaded»>
            <BeginStoryboard Storyboard=»{StaticResource Bear_wmv}»/>
        </EventTrigger>
    </Window.Triggers>
    <Grid>

        <Button Grid.RowSpan=»2″ Grid.ColumnSpan=»2″>
            <Grid Height=»250″ Width=»250″ HorizontalAlignment=»Center»>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width=»142*» />
                    <ColumnDefinition Width=»136*» />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height=»131*» />
                    <RowDefinition Height=»131*» />
                </Grid.RowDefinitions>
                <MediaElement x:Name=»Bear_wmv» Grid.Row=»0″  Grid.Column=»0″ VerticalAlignment=»Top» Height=»123.5″ Grid.ColumnSpan=»2″ Margin=»0,0,8,0″ />
               <Image Source=»bluemonster.jpg» Grid.Column=»0″ Grid.Row=»1″></Image>
            </Grid>
        </Button>
    </Grid>
</Window>

 

De hecho, lo que ha insertado la imagen es el siguiente fragmento:

<Image Source=»bluemonster.jpg» Grid.Column=»0″ Grid.Row=»1″></Image>

El cual nos dice. etiqueta del tipo imagen, fuente=la imágen que hemos insertado, ponla en la definicion de columnas # 0 y filas #1, son como coordenadas. El resultado:

imagen

Finalmente, agregaremos un textbox dentro del botón, esto se hace con el código:

<Window x:Class=»Window2″
    xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
    xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
    Title=»Window1″ Height=»300″ Width=»300″ xmlns:d=»http://schemas.microsoft.com/expression/blend/2008″ xmlns:mc=»http://schemas.openxmlformats.org/markup-compatibility/2006″ mc:Ignorable=»d»>
    <Window.Resources>
        <Storyboard x:Key=»Bear_wmv»>
            <MediaTimeline BeginTime=»00:00:00″ Storyboard.TargetName=»Bear_wmv» Source=»Bear.wmv»/>
        </Storyboard>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent=»FrameworkElement.Loaded»>
            <BeginStoryboard Storyboard=»{StaticResource Bear_wmv}»/>
        </EventTrigger>
    </Window.Triggers>
    <Grid>

        <Button Grid.RowSpan=»2″ Grid.ColumnSpan=»2″>
            <Grid Height=»250″ Width=»250″ HorizontalAlignment=»Center»>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width=»142*» />
                    <ColumnDefinition Width=»136*» />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height=»131*» />
                    <RowDefinition Height=»131*» />
                </Grid.RowDefinitions>
                <MediaElement x:Name=»Bear_wmv» Grid.Row=»0″  Grid.Column=»0″ VerticalAlignment=»Top» Height=»123.5″ Grid.ColumnSpan=»2″ Margin=»0,0,8,0″ />
                <Image Source=»bluemonster.jpg» Grid.Column=»0″ Grid.Row=»1″></Image>
                <TextBox Text=»Hello world» Grid.Column=»1″ Grid.Row=»1″ TextAlignment=»Center»></TextBox>
            </Grid>
        </Button>
    </Grid>
</Window>

 

La línea que nos crea el textbox es:

<TextBox Text=»Hello world» Grid.Column=»1″ Grid.Row=»1″ TextAlignment=»Center»></TextBox>

Que es prácticamente lo mismo que el de la imágen, con la diferencia de que estamos creando un Textbox, no una Image.

textbox

Pero para hacerlo un poco mas interesante, vamos a agregarle un color de fondo a nuestro Textbox, pero no será cualquier color, será un degradado, esto es muy fácil con WPF, tan solo con insertar el texto:

               <TextBox.Background> = Definimos que queremos rellenar el Background o fondo
                        <LinearGradientBrush EndPoint=»0.5,1″ StartPoint=»0.5,0″> = Decimos que será un gradiente linear, con un punto inicial en (.5,0) y un punto final en (.5,1) de nuestro textbox.
                            <GradientStop Color=»#FF000000″ Offset=»1″/> = Definimos uno de los colores de nuestro gradiente, en este caso Blanco, y con una «distancia» de 1
                            <GradientStop Color=»#FFFFFFFF» Offset=»0.013″/> = lo mismo que el anterior código, pero con un color negro
                        </LinearGradientBrush> =cierre de etiquetas
                </TextBox.Background> = Cierre de etiquetas

Lo que nos arroja lo siugente:

textbox2

Y listo, tenemos nuestro Textbox rellenado.le he cambiado el color de la letra para que se distinguiera mejor.

Aquí el código completo:

<Window x:Class=»Window2″
    xmlns=»http://schemas.microsoft.com/winfx/2006/xaml/presentation»
    xmlns:x=»http://schemas.microsoft.com/winfx/2006/xaml»
    Title=»Window1″ Height=»300″ Width=»300″ xmlns:d=»http://schemas.microsoft.com/expression/blend/2008″ xmlns:mc=»http://schemas.openxmlformats.org/markup-compatibility/2006″ mc:Ignorable=»d»>
    <Window.Resources>
        <Storyboard x:Key=»Bear_wmv»>
            <MediaTimeline BeginTime=»00:00:00″ Storyboard.TargetName=»Bear_wmv» Source=»Bear.wmv»/>
        </Storyboard>
    </Window.Resources>
    <Window.Triggers>
        <EventTrigger RoutedEvent=»FrameworkElement.Loaded»>
            <BeginStoryboard Storyboard=»{StaticResource Bear_wmv}»/>
        </EventTrigger>
    </Window.Triggers>
    <Grid>

        <Button Grid.RowSpan=»2″ Grid.ColumnSpan=»2″>
            <Grid Height=»250″ Width=»250″ HorizontalAlignment=»Center»>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width=»142*» />
                    <ColumnDefinition Width=»136*» />
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height=»131*» />
                    <RowDefinition Height=»131*» />
                </Grid.RowDefinitions>
                <MediaElement x:Name=»Bear_wmv» Grid.Row=»0″  Grid.Column=»0″ VerticalAlignment=»Top» Height=»123.5″ Grid.ColumnSpan=»2″ Margin=»0,0,8,0″ />
                <Image Source=»bluemonster.jpg» Grid.Column=»0″ Grid.Row=»1″></Image>
                <TextBox Text=»Hello world» Grid.Column=»1″ Grid.Row=»1″ TextAlignment=»Center» Foreground=»#FF8617A8″>
                    <TextBox.Background>
                        <LinearGradientBrush EndPoint=»0.5,1″ StartPoint=»0.5,0″>
                            <GradientStop Color=»#FF000000″ Offset=»1″/>
                            <GradientStop Color=»#FFFFFFFF» Offset=»0.013″/>
                        </LinearGradientBrush>
                    </TextBox.Background>
                </TextBox>
            </Grid>
        </Button>
    </Grid>
</Window>

Y viendo la estructura jeráquica que hemos deifnido, quedaría así:

arbol1

Como veis, dentro de nuestra ventana de windows, tenemos nuestra primera grila, luego viene nuestro botón, sobre el cual hay insertada otra grilla, dentro de la misma tenemos un video, una imagen y un Textbox. 🙂

Vale, como véis, es bantante sencillo usar XAML, sin embargo, a veces por cuestión de tiempo, es mejor usar herramientas visuales, tales como la suite expression, de la cual hablaremos en nuestra próxima entrada, Hasta la vista!! y espero no haberlos aburrido

Salu2

Héctor Pérez