¿Por qué mola WPF?
Hola!!
Lo prometido es deuda, así que vamos a escribir el por qué mola WPF.
¿Por qué mola WPF?
Microsoft ha estado analizando qué cosas hacia falta mejorar y hacer más cómodas en la programación de escritorio y con esos datos pues creó WPF, una librería que automatiza y nos pone fácil muchas de esas cosas que con otra librería sería difícil de conseguir.
Así que me gustaría hacer un pequeño tour mostrando las features más llamativas de WPF y transmitiros la misma sensación que yo tuve cuando las descubrí.
XAML
XAML, pronunciado “Zammel” es el nuevo lenguaje creado por Microsoft para la creación de interfaces de usuario en WPF y Silverlight.
XAML es muy parecido al XML de toda la vida y además la creación de interfaces nos recordará mucho a crear una web con XHTML.
Por ejemplo, crear un botón sería tan fácil como esto:
<Button Content=”OK” Click=”evento_click” />
Como podéis ver, es bastante sencillo de entender, hemos creado un botón y establecido propiedades y eventos. Vamos, sería algo del tipo:
<Objeto PropiedadX=”...” PropiedadY=”...” EventoZ=”...” />
Podéis asignar cualquier número de propiedades y eventos, o ninguno vaya.
También podéis crear objetos de la siguiente forma:
<Button Width=”100” Height=”100”> …. </Button>
Ésta forma es para tener más control de lo que hace el botón, pero eso ya está fuera del alcance de este tour.
La idea de XAML es buena porque un diseñador no tiene que saber nada de programación. Simplemente conociendo XAML podrá crear cualquier tipo de interfaz gráfica sin saber nada de C# o VB.NET (o IronPython, etc)
Otra cosa importante de XAML, aunque no es nuevo, viene bien recordarlo, y es que los hijos de los elementos pueden heredar cosas del padre, así que si el padre implementa cualquier cosa, el hijo también lo hará, aunque si al hijo le vuelves a implementar la misma cosa, se aplicará este último (Luego lo veremos con más detalle).
Layouts y Attached Properties
Si habéis creado interfaces por ejemplo con Swing alguna vez, ya conoceréis los layouts, o sea, esa manera que tenemos de organizar los controles por la interfaz.
WPF tiene menos layouts que Swing por ejemplo, pero si son más potentes gracias a las features que nos da WPF.
Voy a presentar algunos para que los conozcáis:
DockPanel: Es probablemente mi layout favorito. Con este layout podremos asignar controles a distintas partes de una ventana, por ejemplo un menú en la parte de arriba, un statusbar en la parte de abajo, una barra a la izquierda… Con la particularidad, que el último elemento que añadamos podrá usar el espacio restante de la ventana si así lo deseamos.
También podemos añadir varios controles al mismo lado de la ventana.
Veamos un ejemplo:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<DockPanel>
<Menu DockPanel.Dock="Top">
<MenuItem Header="Fichero" />
</Menu>
<StatusBar DockPanel.Dock="Bottom">
<TextBlock Text="Barra de estado" />
</StatusBar>
<TextBlock Text="Hola mundo" />
</DockPanel>
</Window>
Aquí como podéis ver, el hijo de la ventana es un DockPanel y dentro hemos creado 3 cosas diferentes:
- Un Menu
- Un StatusBar
- Un TextBlock
El menú lo hemos anclado a la parte superior de la ventana, el statusbar en la parte inferior, y en la parte que sobra, hemos puesto un textblock con un mensajito.
Aquí es donde entran en juego las attached properties, ésto es uno de los nuevos features de WPF y es bastante interesante y da mucho juego.
Las attached properties son una forma de “propagar” las propiedades de una clase a otra clase distinta, o sea, es una forma de usar ciertas propiedades en una clase que de otra forma sería imposible.
Por ejemplo, si tenemos una lista y cada elemento de una lista tiene un botón en el cual todos hacen la misma función (borrar el elemento de la lista), podríamos decirle a cada botón que escuche el evento clicked y que todos apunten al mismo controlador del evento. Es una buena solución, pero con las attached properties podemos decirle a la lista en si, que implemente el evento clicked del botón y que borre el elemento seleccionado. Así solo tendríamos un controlador y el evento puesto en un solo lado y no en cada botón que creemos. ¿Cómo hacemos esto? Simplemente “propagamos” el evento clicked de la clase Button y ya todos sus hijos pues lo implementarán por lo que dije antes de heredar lo del padre.
Esa lista en concreto se podría haber creado así:
<ListBox ButtonBase.Click="..."> ... </ListBox>
Como veis, le digo que implemente una attached properties, en concreto el evento clicked de un botón.
Volviendo a nuestro ejemplo del DockPanel, podeis ver que los distintos hijos de éste, usan una attached properties del propio DockPanel, en este caso, dicha attached properties nos sirve para colocar los controles en las distintas partes de la ventana. ¿Mola verdad? Así no hay que ir diciendole al DockPanel que añada tales controles en tales partes, ya son los propios controles los que lo deciden.
Vamos a ver ahora algún layout más, por ejemplo el StackPanel. El StackPanel como su nombre indica, es un tipo de layout donde los elementos que vayamos añadiendo se irán colocando unos debajo de otro. Veamos un ejemplo:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<StackPanel>
<Button Content="Boton" />
<TextBlock Text="Texto" />
<Rectangle Fill="Aquamarine" Stroke="Black"
StrokeThickness="1" Height="30" />
</StackPanel>
</Window>
Nada nuevo por aquí. Creamos el StackPanel y dentro de este vamos colocando controles los cuales se irán colocando uno debajo del otro.
Por último vamos a enseñar el que probablemente es el layout más flexible. El Grid.
Veamos el ejemplo primero:
<Window x:Class="WpfApplication1.Window1"
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="auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="auto" />
<RowDefinition Height="auto" />
</Grid.RowDefinitions>
<TextBlock Text="Nombre: " />
<TextBox Grid.Column="1" />
<TextBlock Grid.Row="1" Text="Email: " />
<TextBox Grid.Row="1" Grid.Column="1" />
</Grid>
</Window>
En el Grid, tenemos que definir el numero de columnas y filas, además de establecer alguna de sus propiedades (opcional).
El Grid es bastante flexible y personalizable. Es este caso he creado una tabla 2×2 como podeis ver. Lo interesante es que podemos definir el tamaño de cada fila/columna de la forma que queramos. En este caso casi todas están en auto, lo que quiere decir es que tendrán el tamaño exacto que ocupe el elemento más grande que contiene, lo cual está bastante bien. Una de las columnas tiene el tamaño puesto en “*” eso quiere decir que use el espacio restante, o sea, si la ventana ocupa 300 pixeles de ancho y en la otra columna el elemento más ancho ocupa 50 pixeles, la otra columna ocupará pues 250 pixeles, que es pues el espacio restante.
El resto de código ya no es tan complicado, como podéis ver, hacemos uso de las attached properties para colocar cada control dentro de la zona del Grid que queramos.
Aparte de estos layouts existen otros varios, pero ya se sale del este tour.
La propiedad Content
Ésta es probablemente una de mis features favoritas de WPF y sin duda una de las más alabadas.
Muchos de los controles de WPF tienen una propiedad llamada Content. Ésta propiedad es la que usamos para describir lo que hay dentro de los controles.
Por ejemplo, en un botón, la propiedad Content la usaremos para especificar el texto que usará el botón, o sea:
<Button Content="OK" />
También podría ser escrito de la siguiente forma:
<Button>OK</Button>
Este ultimo funciona bien gracias a una feature de WPF llamada Type Converters que convierte esa cadena en un elemento del tipo TextBlock, pero vamos, eso lo explicaré en su dia en otro artículo pues está fuera del alcance de este. Además, lo que pongas entre la etiqueta de abrir y la de cerrar, será el Content del objeto.
Ustedes os preguntaréis, ¿Cual es la parte que mola? Pues esto lo hacen todos los “rivales” de WPF.
Faaaaacil, la propiedad Content de los controles, es del tipo Object lo cual nos permitirá poner CUALQUIER COSA como contenido de ese control.
Ya os veo imaginando las posibilidades de esto, no sé, para poner alguna disparatada… Un navegador dentro de un botón, una lista en la que cada elemento sea como tu quieras, un menú que muestre videos como iconos…
Y sobretodo, poder poner un panel como la propiedad Content y así tener mucha más flexibilidad.
Imaginad que estais haciendo un reproductor de audio o video (que dicho sea de paso, es algo trivial en WPF) y quereis personalizar un poco los botones, y por ejemplo, un botón que ponga “Stop” asi a pelo pues no mola tanto:
<Button Content="Stop" />
Sin embargo molaría más que además tuviera el icono del stop, así que podríamos hacer:
<Window x:Class="WpfApplication1.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<Button Height="23" Name="button1" Width="75">
<StackPanel Orientation="Horizontal">
<Rectangle Width="10" Height="10" Fill="Black" />
<TextBlock Margin="10, 0, 0, 0" Text="Stop" />
</StackPanel>
</Button>
</Window>
¿Mejor verdad? Hemos creado un boton donde su Content sea un StackPanel (orientado horizontalmente) y ahi meter un cuadradito negro y un texto. Podeis cambiar el cuadradito por otra cosa más sotisficada como una imagen o lo que querais.
Ejemplos más completos requieren de features que desconoceis, así que después pondré un ejemplo más chulo sobre este tema.
Data Binding
Otra de las features clave de WPF. Los Data Binding no son una cosa nueva de WPF ni mucho menos, pero WPF las lleva a otro nivel y son suuuuuuper sencillas de usar.
Para los nuevos, ¿Qué son los Data Bindings?. Son básicamente una forma de enlazar una propiedad de un objeto con la propiedad de otro objeto. Puede ser entre controles, entre un control y una clase nueva…
Vaaamos con un ejemplo que será lo mejor:
<Window x:Class="PQMW.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300">
<DockPanel>
<Slider DockPanel.Dock="Bottom" x:Name="alto"
Minimum="25" Maximum="200"/>
<Slider DockPanel.Dock="Left" x:Name="ancho"
Minimum="25" Maximum="200"
Orientation="Vertical" />
<Ellipse Width="{Binding Value, ElementName=ancho}"
Height="{Binding Value, ElementName=alto}"
Fill="Blue" Stroke="Black" StrokeThickness="1" />
</DockPanel>
</Window>

Aqui un siiiiiimple ejemplo, tenemos una ventana con 2 Sliders y un Elipse, el elipse irá creciendo variando en tamaño conforme movamos los sliders (¡Y todo esto sin código!). ¿Cómo? Pues con los Data bindings
Lo interesante del XAML es el elipse en si:
<Ellipse Width="{Binding Value, ElementName=ancho}"
Height="{Binding Value, ElementName=alto}"
Fill="Blue" Stroke="Black" StrokeThickness="1" />
Ahi podéis ver las propiedades Width y Height con una sintaxis más extraña de la que ya conoceis.
Lo que está dentro de las llaves se llama Markup Extensions y que básicamente son una forma de extender la expresividad de XAML hasta limites insospechados. Las cadenas que metemos son evaluadas en tiempo de ejecución (casi todas) lo cual pues está bien. Iremos viendo ejemplos de Markup Extensions más adelante.
En este caso, el Binding es un markup extension y su sintaxis es básica:
Propiedad=”{Binding Propiedad, ElementName=elementoABindear}”
Bueno, realmente no es una sintaxis fija, puedes ignorar el ElementName si el contexto donde esté el control sea el objeto a usar y bla bla, vamos, esto es más bien para presenter el binding en si, hablar de todo su poder lleva unas 30 páginas de un libro o más.
Errr a lo que iba… En este caso, podeis ver que anclamos el ancho del elipse a la propiedad Value del elemento ancho (el slider de abajo). Lo mismo con la propiedad alto pero con el otro slider.
Entonces, cada vez que deslizo los sliders, las propiedades del elipse van cambiando también.
Estilos
¡Las interfaces WPF pueden ser estilizadas como si con CSS se tratase! Pero eso si, esto es más potente que el CSS
.
Por ejemplo, basándonos en el ejemplo anterior del elipse con los sliders, vamos al fichero app.xaml del proyecto y lo dejamos así:
<Application x:Class="PQMW.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="Window1.xaml">
<Application.Resources>
<Style TargetType="{x:Type Ellipse}">
<Setter Property="Fill">
<Setter.Value>
<LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
<GradientStop Color="Yellow" Offset="0.0" />
<GradientStop Color="Red" Offset="0.25" />
<GradientStop Color="Blue" Offset="0.75" />
<GradientStop Color="LimeGreen" Offset="1.0" />
</LinearGradientBrush>
</Setter.Value>
</Setter>
<Setter Property="Stroke" Value="Black" />
<Setter Property="StrokeThickness" Value="2" />
</Style>
</Application.Resources>
</Application>
Los estilos se crean con la etiqueta Style y en dicha etiqueta definimos el TargetType donde usando un markup extension podemos especificar el control concreto en el que se aplicará el estilo. Con esto, todos los elementos de ese tipo, que estén dentro del “foco” de donde hayamos creado el estilo (al crearlo en el app.xaml, el estilo es aplicado en toooooda la aplicación, pero podriamos haberlo creado en una ventana y solo se aplicaría a dicha ventana.)
Además, podriamos crear un estilo que solo se aplicara a los elementos que nosotros quisieramos, simplemente añadiendo la propiedad Key con un nombre y usar dicho nombre para aplicar los estilos manualmente, pero ya sabes, eso está fuera del ambito de este artículo.
Bueno, siguiendo con el estilo. Crear un estilo es fácil. Simplemente es ir colocando Setters para cada propiedad que queramos. Cada setter lleva 2 propiedades, en property especificamos la propiedad a modificar, y en value el valor que queramos darle.
Como podeis ver, el valor no tiene por que ser simple. Puede ser tan complejo como quieras, y ahi en el ejemplo podeis ver como a la propiedad Fill le metemos un degradado ahi majo en vez de un color liso.
Luego, el elipse de la aplicación no deberá hacer nada para aplicar el estilo, así que quedaría así:
<Ellipse Width="{Binding Value, ElementName=ancho}"
Height="{Binding Value, ElementName=alto}"/>
Si ahi colocamos por ejemplo la propiedad Fill, se sobreescribiria la del estilo.
Los estilos son herramientas MUY potentes que nos permiten crear estilos para nuestras aplicaciones de forma fácil como si fuese el CSS de una web. Realmente se puede hacer muchisimo más de lo aqui expuesto, pero eso se deja para otro artículo.
Triggers
Los Triggers son una especie de lanzadores que se ejecutan cuando se dan ciertos casos.
Por ejemplo, podría crear uno para que cuando pase el raton por uno de los sliders, aparece un brillo rojo alrededor de el y que cuando saque el ratón de ahi se quite. Se podría crear un evento para el “mouseenter” y el “mouseleft” para poner o quitar el brillo respectivamente. También se podrían utilizar triggers.
Abre el app.xaml y justo debajo del estilo del elipse, escribe:
<Style TargetType="{x:Type Slider}">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="BitmapEffect">
<Setter.Value>
<OuterGlowBitmapEffect GlowColor="Red" GlowSize="4"/>
</Setter.Value>
</Setter>
</Trigger>
</Style.Triggers>
</Style>
La sintaxis es como la de los estilos, solo que esta vez meteremos el setter dentro de un Trigger.
No me voy a marear demasiado en explicar su sintaxis, puesto que seria mejor hacerlo en otro artículo, pero básicamente comprueba si el ratón está encima del control y si está aplica un brillo de color rojo.
Como verás, con los triggers se pueden hacer muchas cositas como girar un boton cuando lo selecciones, o que de vueltas o no sé, ahi entra tu imaginación.
Resumen
Ésta es la punta del iceberg de WPF. Éstas son algunas de las cosas que hace que WPF sea GRANDE.
Hay más cosas que me he dejado en el tintero, ya sean porque todavia no las conozco lo suficiente como para haberlas incluido y otras porque sería complicar mucho el artículo.
Pero aun así, espero que este artículo os haya hecho ver lo que es WPF y lo que puede hacer por vosotros.
Por otro lado, cada aspecto aquí presentado lo está de una forma básica y cada una de esas cosas dan mucho más de si.
Además WPF permite hacer dibujos 2D, 3D, animaciones, transformar elementos para girarlos o doblarlos…
Pero vamos, la gracia es la que está aqui presentada.
Si habeis llegado hasta aquí, dejad un comentario que no tardareis mucho





Ilgrim said,
Wrote on Junio 5, 2009 @ 18:50
Pues como pronto… debo decirte que tenias razon… Se deja entre ver bastante potencial de todo esto…. Habra que seguir viendo como evolucionan estos post tuyos…
Por ahora parece ser muy interesante el tema de WPF.
Kans said,
Wrote on Junio 5, 2009 @ 20:27
¡Felicidades por el post! te ha quedado muy currado; y WPF en sí me parece bastante bueno… me gusta
BlackEye said,
Wrote on Junio 5, 2009 @ 23:15
A ver si acabo los exámenes y me voy con el WPF…porque me estás poniendo los dientes largos >.<
Muy bien explicado todo
Wilson said,
Wrote on Septiembre 17, 2009 @ 17:20
Felicidades, lo lei hasta la mitad(obviamente lo terminare de leer) y me eliminaste demasiadas dudas, y ya de plano me gusto..
Un consejo, deberias sacar algun libro…
Wilson said,
Wrote on Septiembre 17, 2009 @ 17:35
Ya siguiendo tu forma de explicar, que tal si pones algo de DependencyProperty?, es un poco complicado de entender para un novato como yo jeje… estaria muy agradecido…
PD: Te animaste a dar la certificacion de WPF 70-502?
Fox said,
Wrote on Septiembre 17, 2009 @ 18:13
Vaya, comentarios que no son spam.
Gracias por tus felicitaciones, los comentarios siempre vienen bien.
¿Un libro? Nah, todavía soy un joven padawan.
Tengo en mi lista el escribir un artículo sobre DependencyProperty, aunque todavía tiene algún secreto para mi, aunque intentaré mirarme las cosillas que me faltan al respecto y a ver si este fin de semana puedo ponerme con ello, que entre la epoca de examenes (la cual ya pasó) y ahora que entré a trabajar, parece que tengo esto muy abandonado.
Y la certificación, no todavía, tengo otras prioridades.