<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://geeks.ms/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>Wiki sobre WPF en Geeks•ms</title><link>http://geeks.ms/wikis/wpf/default.aspx</link><description>Wiki sobre Windows Presentation Foundation</description><dc:language>en-US</dc:language><generator>CommunityServer 2008.5 SP1 (Build: 31106.3070)</generator><item><title>WPF: Integrando nuestra aplicación con la Barra de Tareas de Windows 7 (II)</title><link>http://geeks.ms/wikis/wpf/wpf-integrando-nuestra-aplicaci-243-n-con-la-barra-de-tareas-de-windows-7-ii/revision/0.aspx</link><pubDate>Tue, 03 Aug 2010 19:10:50 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:15</guid><dc:creator>Josué Yeray Julián Ferreiro</dc:creator><description>Revisión actual enviado a Wiki sobre WPF en Geeks•ms por Josué Yeray Julián Ferreiro a 8/3/2010 9:10:50 PM&lt;br /&gt;
&lt;p&gt;Hola! &lt;/p&gt;
&lt;div align="justify"&gt;En el art&amp;iacute;culo anterior sobre integraci&amp;oacute;n de nuestra aplicaci&amp;oacute;n con la barra de tareas de Windows 7 (puedes verlo &lt;a target="_blank" href="http://jyeray.blogspot.com/2010/07/wpf-integrando-nuestra-aplicacion-con.html"&gt;aqu&amp;iacute;&lt;/a&gt;) habl&amp;aacute;bamos sobre las formas que nos ofrece la barra de tareas de Windows 7 de comunicar informaci&amp;oacute;n a nuestros usuarios, usando la sobreimpresi&amp;oacute;n de iconos y la barra de progreso.&lt;/div&gt;
&lt;div align="justify"&gt;En todo programa la comunicaci&amp;oacute;n es bidireccional, por un lado comunicamos informaci&amp;oacute;n al usuario y por otro esperamos que el usuario nos proporcione informaci&amp;oacute;n con la que trabajar, ya que hemos conseguido adaptar a Windows 7 la forma en la que nuestro usuario recibe informaci&amp;oacute;n, hagamos ahora que pueda de forma sencilla e intuitiva comunicarnos informaci&amp;oacute;n desde la barra de tareas.&lt;/div&gt;
&lt;!--more--&gt;
&lt;div align="justify"&gt;&lt;/div&gt;
&lt;div align="justify"&gt;Para esto, en este art&amp;iacute;culo, trataremos sobre las JumpList y los Thumbnail Toolbars:&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Jumplist:&lt;/strong&gt; Las Jumplist son enlaces r&amp;aacute;pidos a partes de nuestra aplicaci&amp;oacute;n que aparecen al hacer click derecho sobre el icono de la misma en la barra de tareas, podemos hacer que nuestra app vaya directamente a una ventana en concreto, sin haberla arrancado todav&amp;iacute;a. &lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Thumbnail Toolbars:&lt;/strong&gt; al pasar el rat&amp;oacute;n sobre los iconos de aplicaciones activas, Windows 7 nos ofrece una preview de la ventana de esa aplicaci&amp;oacute;n, con las Thumbnail Toolbars podemos a&amp;ntilde;adir botones a esa vista que ejecuten ordenes en nuestra aplicaci&amp;oacute;n. &lt;/li&gt;
&lt;/ol&gt;
&lt;h4&gt;.NET 3.5 vs .NET 4&lt;/h4&gt;
&lt;div align="justify"&gt;Para acceder a todas estas caracter&amp;iacute;sticas en .NET 3.5 solo ten&amp;iacute;amos un camino: Interoperabilidad con el api no manejada de Win32 (al igual que con el art&amp;iacute;culo sobre la gesti&amp;oacute;n de energ&amp;iacute;a), sin embargo para .NET 4 han integrado las funcionalidades de la barra de tareas de Windows 7 en el propio framework, por lo que el &amp;ldquo;uso y disfrute&amp;rdquo; de estas caracter&amp;iacute;sticas es much&amp;iacute;simo m&amp;aacute;s sencillo. Por ello el c&amp;oacute;digo de este art&amp;iacute;culo es solo &amp;uacute;til para .NET 4.&lt;/div&gt;
&lt;h4&gt;Empecemos&lt;/h4&gt;
&lt;div align="justify"&gt;Vamos a comenzar, lo primero es crear un nuevo proyecto WPF Application (File &amp;gt; New &amp;gt; Project), una vez creado, vamos a dise&amp;ntilde;ar la pantalla principal en el archivo MainWindow.xaml&lt;/div&gt;
&lt;div align="justify"&gt;Los estilos que he usado en esta aplicaci&amp;oacute;n est&amp;aacute;n disponibles en la descarga en el archivo Application.xaml, si ten&amp;eacute;is dudas acerca de como usar / crear estilos, echadle un vistazo a mis dos art&amp;iacute;culos sobre este tema: &lt;a target="_blank" href="http://jyeray.blogspot.com/2010/05/wpf-personalizar-nuestra-aplicacion-con.html"&gt;aqu&amp;iacute;&lt;/a&gt; y &lt;a target="_blank" href="http://jyeray.blogspot.com/2010/06/wpf-personalizar-nuestra-aplicacion-con.html"&gt;aqu&amp;iacute;&lt;/a&gt;&lt;/div&gt;
&lt;div align="justify"&gt;Bien, para empezar a trabajar con la barra de tareas debemos a&amp;ntilde;adir en xaml un objeto de tipo TaskbarItemInfo:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Window.TaskbarItemInfo&amp;gt;
&amp;lt;TaskbarItemInfo/&amp;gt;
&amp;lt;/Window.TaskbarItemInfo&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Con esto ya tendremos acceso a multitud de propiedades de la barra de tareas de windows 7 de forma sencilla y r&amp;aacute;pida.&lt;/div&gt;
&lt;h4&gt;JumpList&lt;/h4&gt;
&lt;div align="center"&gt;&lt;a href="http://lh6.ggpht.com/_7YCdMP8inuc/TFhIsYMErPI/AAAAAAAAAGU/HhkWde0Jjzg/s1600-h/JumpList4.png"&gt;&lt;img height="405" width="308" src="http://lh6.ggpht.com/_7YCdMP8inuc/TFhIt7A-m-I/AAAAAAAAAGY/RGv8vMvb9RU/JumpList_thumb2.png?imgmax=800" alt="JumpList" border="0" title="JumpList" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt;&amp;nbsp;&lt;/div&gt;
&lt;div align="justify"&gt;Vamos a empezar a trabajar con las &lt;strong&gt;JumpList&lt;/strong&gt;, lo primero que tenemos que hacer es abrir el c&amp;oacute;digo del archivo &lt;strong&gt;application.xaml&lt;/strong&gt; y a&amp;ntilde;adir un nuevo manejador de eventos para el evento &lt;strong&gt;Startup&lt;/strong&gt;:&lt;/div&gt;
&lt;pre class="brush: vb;"&gt;Private Sub Application_Startup(ByVal sender As Object, 
ByVal e As System.Windows.StartupEventArgs) 
Handles Me.Startup
End Sub&lt;/pre&gt;
&lt;div align="justify"&gt;La forma en la que los elementos de la &lt;strong&gt;Jumplist&lt;/strong&gt; se comunicar&amp;aacute;n con nuestra aplicaci&amp;oacute;n es mediante argumentos a la hora de ejecutarla, por lo que en el evento &lt;strong&gt;Startup&lt;/strong&gt; realizaremos dos trabajos, por un lado comprobaremos si nos ha llegado un par&amp;aacute;metro y ejecutaremos el c&amp;oacute;digo asociado al mismo y por otro lado en este evento crearemos nuestra lista y se la notificaremos a la aplicaci&amp;oacute;n.&lt;/div&gt;
&lt;div align="justify"&gt;Para controlar los argumentos pasados a la aplicaci&amp;oacute;n usaremos la propiedad Args de la variable e del evento, usando un bloque Select Case para ello de la siguiente forma:&lt;/div&gt;
&lt;pre class="brush: vb;"&gt;If e.Args.Count &amp;gt; 0 Then
Select Case e.Args(0)
Case &amp;quot;update&amp;quot;
MessageBox.Show(&amp;quot;No existen actualizaciones&amp;quot;)
Case &amp;quot;searchclient&amp;quot;
MessageBox.Show(&amp;quot;Has seleccionado Buscar Clientes&amp;quot;)
Case &amp;quot;searchinvoice&amp;quot;
MessageBox.Show(&amp;quot;Has seleccionado Buscar Facturas&amp;quot;)
End Select
End If&lt;/pre&gt;
&lt;div align="justify"&gt;Como pod&amp;eacute;is ver es muy simple, al crear nuestra &lt;strong&gt;JumpList&lt;/strong&gt; a cada Elemento le hemos asociado un argumento (update, searchclient o searchinvoice) al seleccionar un elemento este ejecuta nuestra aplicaci&amp;oacute;n envi&amp;aacute;ndole el argumento que le hemos asociado y nosotros al recibirlo podemos ejecutar el c&amp;oacute;digo pertinente.&lt;/div&gt;
&lt;div align="justify"&gt;Ahora vamos a crear los elementos de la &lt;strong&gt;JumpList&lt;/strong&gt;, para esto usaremos el objeto &lt;strong&gt;JumpTask&lt;/strong&gt; del namespace &lt;strong&gt;Shell&lt;/strong&gt;:&lt;/div&gt;
&lt;pre class="brush: vb;"&gt;Dim BuscarActualizaciones As New Shell.JumpTask
BuscarActualizaciones.Title = &amp;quot;Buscar Actualizaciones&amp;quot;
BuscarActualizaciones.Arguments = &amp;quot;update&amp;quot;
BuscarActualizaciones.Description = &amp;quot;Comprobamos si existen actualizaciones.&amp;quot;
BuscarActualizaciones.CustomCategory = &amp;quot;Mantenimiento&amp;quot;
BuscarActualizaciones.IconResourcePath = Assembly.GetEntryAssembly().CodeBase
BuscarActualizaciones.ApplicationPath = Assembly.GetEntryAssembly().CodeBase

Dim BuscarCliente As New Shell.JumpTask
BuscarCliente.Title = &amp;quot;Buscar Cliente&amp;quot;
BuscarCliente.Arguments = &amp;quot;searchclient&amp;quot;
BuscarCliente.Description = &amp;quot;Busqueda para localizar un cliente.&amp;quot;
BuscarCliente.CustomCategory = &amp;quot;Clientes&amp;quot;
BuscarCliente.IconResourcePath = Assembly.GetEntryAssembly().CodeBase
BuscarCliente.ApplicationPath = Assembly.GetEntryAssembly().CodeBase

Dim ConsultarFacturas As New Shell.JumpTask
ConsultarFacturas.Title = &amp;quot;Consultar Facturas&amp;quot;
ConsultarFacturas.Arguments = &amp;quot;searchinvoice&amp;quot;
ConsultarFacturas.Description = &amp;quot;Ver la lista de facturas&amp;quot;
ConsultarFacturas.CustomCategory = &amp;quot;Facturaci&amp;oacute;n&amp;quot;
ConsultarFacturas.IconResourcePath = Assembly.GetEntryAssembly().CodeBase
ConsultarFacturas.ApplicationPath = Assembly.GetEntryAssembly().CodeBase&lt;/pre&gt;
&lt;p&gt;Simplemente definimos las caracter&amp;iacute;sticas de cada &lt;strong&gt;JumpTask&lt;/strong&gt;, ahora solo nos queda agregarlos a una &lt;strong&gt;JumpList&lt;/strong&gt;: &lt;/p&gt;
&lt;pre class="brush: vb;"&gt;Dim Lista As New Shell.JumpList
Lista.JumpItems.Add(BuscarActualizaciones)
Lista.JumpItems.Add(BuscarCliente)
Lista.JumpItems.Add(ConsultarFacturas)&lt;/pre&gt;
&lt;p&gt;Por &amp;uacute;ltimo, tenemos que indicar al sistema que relacione esta Lista con nuestra aplicaci&amp;oacute;n, usando el m&amp;eacute;todo &lt;strong&gt;SetJumpList&lt;/strong&gt; de la clase &lt;strong&gt;JumpList&lt;/strong&gt;: &lt;/p&gt;
&lt;pre class="brush: vb;"&gt;Shell.JumpList.SetJumpList(Application.Current, Lista)&lt;/pre&gt;
&lt;div align="justify"&gt;Aunque este c&amp;oacute;digo se ejecutar&amp;aacute; siempre que arranquemos la aplicaci&amp;oacute;n, nunca se duplicar&amp;aacute;n los elementos de la &lt;strong&gt;JumpList&lt;/strong&gt; pues el sistema se encargar&amp;aacute; cada vez que le pasemos una &lt;strong&gt;JumpList&lt;/strong&gt; de actualizar los elementos que ya tiene asignados, en caso de que hayamos realizado alg&amp;uacute;n cambio, de crear los nuevos elementos o de eliminar los elementos que ya no existan.&lt;/div&gt;
&lt;p&gt;Con esto si ejecutas la aplicaci&amp;oacute;n y presionas con el bot&amp;oacute;n derecho en el icono de la misma en la barra de tareas ver&amp;aacute;s los elementos creados por nosotros, si seleccionas alguno ver&amp;aacute;s que aparece el mensaje correspondiente y se abre una nueva instancia de la aplicaci&amp;oacute;n: &lt;/p&gt;
&lt;div align="center"&gt;&lt;a href="http://lh6.ggpht.com/_7YCdMP8inuc/TFhIu2_mxxI/AAAAAAAAAGc/XrMo58t_pXs/s1600-h/jumplist24.png"&gt;&lt;img height="368" width="562" src="http://lh6.ggpht.com/_7YCdMP8inuc/TFhIwOEN_6I/AAAAAAAAAGg/Gf8QxSIzDjw/jumplist2_thumb2.png?imgmax=800" alt="jumplist2" border="0" title="jumplist2" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;En conjunto, el dotar a nuestra aplicaci&amp;oacute;n de &lt;strong&gt;JumpList&lt;/strong&gt; no es un proceso complicado, pero a la larga puede darnos muchos beneficios, &amp;iquest;porque hacer pasar a nuestros usuarios por varias ventanas para llegar a consultar o actualizar un dato, cuando podemos ofrecerles las acciones m&amp;aacute;s comunes simplemente con dos clicks y que nuestra aplicaci&amp;oacute;n arranque directamente a donde nuestros usuarios necesitan ir? Si lo piensas detenidamente seguro que se te ocurren mil situaciones donde te abr&amp;iacute;a sido muy c&amp;oacute;modo tener este sistema a mano. Por lo menos en mi experiencia personal esta es una de las caracter&amp;iacute;sticas de Windows 7 que m&amp;aacute;s &amp;uacute;til me resulta.&lt;/div&gt;
&lt;h4&gt;Thumbnail Toolbars&lt;/h4&gt;
&lt;div align="center"&gt;&lt;a href="http://lh3.ggpht.com/_7YCdMP8inuc/TFhIxf0NbTI/AAAAAAAAAGk/QIqGPQMy7tg/s1600-h/Toolbar4.png"&gt;&lt;img height="327" width="278" src="http://lh5.ggpht.com/_7YCdMP8inuc/TFhIywPBPOI/AAAAAAAAAGo/WmEokwpTQR0/Toolbar_thumb2.png?imgmax=800" alt="Toolbar" border="0" title="Toolbar" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;Esta forma de que el usuario interact&amp;uacute;e con nuestra aplicaci&amp;oacute;n se combina de forma perfecta con el contenido de nuestro anterior art&amp;iacute;culo, en el que explic&amp;aacute;bamos como informar al usuario del progreso de nuestra aplicaci&amp;oacute;n sin que tuviese la ventana de la misma a la vista, pues bien, con los thumbnail Toolbars, permitiremos que, una vez recibida esa informaci&amp;oacute;n el usuario pueda responder ejecutando una orden en nuestra aplicaci&amp;oacute;n sin la necesidad de maximizar la ventana.&lt;/div&gt;
&lt;p&gt;Lo primero que vamos a hacer es crear las im&amp;aacute;genes para los botones, usando la clase &lt;strong&gt;DrawingImage&lt;/strong&gt;, como recursos de nuestra ventana: &lt;/p&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Window.Resources&amp;gt;
&amp;lt;DrawingImage x:Key=&amp;quot;IconUpdate&amp;quot;&amp;gt;
&amp;lt;DrawingImage.Drawing&amp;gt;
&amp;lt;ImageDrawing Rect=&amp;quot;0,0,24,24&amp;quot; 
ImageSource=&amp;quot;/Images/update.png&amp;quot; /&amp;gt;
&amp;lt;/DrawingImage.Drawing&amp;gt;
&amp;lt;/DrawingImage&amp;gt;
&amp;lt;DrawingImage x:Key=&amp;quot;IconClient&amp;quot;&amp;gt;
&amp;lt;DrawingImage.Drawing&amp;gt;
&amp;lt;ImageDrawing Rect=&amp;quot;0,0,24,24&amp;quot; 
ImageSource=&amp;quot;/Images/client.png&amp;quot; /&amp;gt;
&amp;lt;/DrawingImage.Drawing&amp;gt;
&amp;lt;/DrawingImage&amp;gt;
&amp;lt;DrawingImage x:Key=&amp;quot;IconInvoice&amp;quot;&amp;gt;
&amp;lt;DrawingImage.Drawing&amp;gt;
&amp;lt;ImageDrawing Rect=&amp;quot;0,0,24,24&amp;quot; 
ImageSource=&amp;quot;/Images/invoice.png&amp;quot; /&amp;gt;
&amp;lt;/DrawingImage.Drawing&amp;gt;
&amp;lt;/DrawingImage&amp;gt;
&amp;lt;/Window.Resources&amp;gt;&lt;/pre&gt;
&lt;p&gt;La clase que usaremos para crear nuestros botones es el &lt;strong&gt;TaskBarItemInfo.ThumbButtonInfo&lt;/strong&gt;: &lt;/p&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Window.TaskbarItemInfo&amp;gt;
&amp;lt;TaskbarItemInfo&amp;gt;
&amp;lt;TaskbarItemInfo.ThumbButtonInfos&amp;gt;
&amp;lt;ThumbButtonInfo x:Name=&amp;quot;btnUpdate&amp;quot;
ImageSource=&amp;quot;{StaticResource IconUpdate}&amp;quot;
Description=&amp;quot;Comprueba actualizaciones&amp;quot;
IsBackgroundVisible=&amp;quot;True&amp;quot;&amp;gt;

&amp;lt;/ThumbButtonInfo&amp;gt;
&amp;lt;ThumbButtonInfo x:Name=&amp;quot;btnClient&amp;quot;
ImageSource=&amp;quot;{StaticResource IconClient}&amp;quot;
Description=&amp;quot;Ver los clientes&amp;quot;
IsBackgroundVisible=&amp;quot;True&amp;quot;&amp;gt;
&amp;lt;/ThumbButtonInfo&amp;gt;
&amp;lt;ThumbButtonInfo x:Name=&amp;quot;btnInvoice&amp;quot;
ImageSource=&amp;quot;{StaticResource IconInvoice}&amp;quot;
Description=&amp;quot;Ver las facturas&amp;quot;
IsBackgroundVisible=&amp;quot;True&amp;quot;&amp;gt;
&amp;lt;/ThumbButtonInfo&amp;gt;
&amp;lt;/TaskbarItemInfo.ThumbButtonInfos&amp;gt;
&amp;lt;/TaskbarItemInfo&amp;gt;
&amp;lt;/Window.TaskbarItemInfo&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;La clase &lt;strong&gt;ThumbButtonInfo&lt;/strong&gt; tiene varias propiedades que nos permitir&amp;aacute;n personalizar la apariencia de nuestro bot&amp;oacute;n:&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;Description:&lt;/strong&gt; Indica el texto que aparecer&amp;aacute; sobre el bot&amp;oacute;n al dejar el rat&amp;oacute;n sobre &amp;eacute;l.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;IsInteractive:&lt;/strong&gt; Esta propiedad permite usar un bot&amp;oacute;n de dos formas:&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div align="justify"&gt;True: el bot&amp;oacute;n se comporta como un bot&amp;oacute;n normal, este es el comportamiento por defecto.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;False: el bot&amp;oacute;n no es interactivo y solo se muestra al usuario, no reaccionando a las acciones de este.&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;IsBackgroundVisible:&lt;/strong&gt; Indica si se resalta el bot&amp;oacute;n al posicionar el rat&amp;oacute;n sobre el o no, por defecto es True.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;DismissWhenClicked:&lt;/strong&gt; Si establecemos a True esta propiedad, cuando pulsemos sobre el bot&amp;oacute;n el Thumbnail se cerrar&amp;aacute;, si es False quedar&amp;aacute; abierto hasta que el rat&amp;oacute;n salga del icono de la barra de tareas, por defecto es False.&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div align="justify"&gt;Ya tenemos creados nuestros botones, si ejecutas la aplicaci&amp;oacute;n y pasas el bot&amp;oacute;n sobre el icono de la barra de tareas ver&amp;aacute;s que aparecen los 3 botones que hemos creado, pero si haces click sobre ellos no ocurre nada.&lt;/div&gt;
&lt;div align="justify"&gt;Ahora debemos programar el comportamiento de los botones, esto lo podemos realizar de dos formas diferentes: usando eventos como cualquier otro bot&amp;oacute;n o usando comandos.&lt;/div&gt;
&lt;div align="justify"&gt;Los dos m&amp;eacute;todos pueden realizar el mismo trabajo pero quiz&amp;aacute;s es m&amp;aacute;s recomendable usar comandos, pues por regla general estos botones ser&amp;aacute;n r&amp;eacute;plicas de otros botones posicionados en la Toolbar principal de la aplicaci&amp;oacute;n o opciones de men&amp;uacute;s y usando comandos podemos enlazar al mismo c&amp;oacute;digo ambos, aun as&amp;iacute; voy a explicar un poco los dos casos.&lt;/div&gt;
&lt;h4&gt;Usando Eventos&lt;/h4&gt;
&lt;div align="justify"&gt;El funcionamiento de los ThumbnailButtonInfo con eventos es muy sencillo y exactamente igual al resto de controles de nuestra aplicaci&amp;oacute;n, simplemente a&amp;ntilde;adimos el evento al que queremos responder desde xaml:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ThumbButtonInfo x:Name=&amp;quot;btnUpdate&amp;quot;
ImageSource=&amp;quot;{StaticResource IconUpdate}&amp;quot;
Description=&amp;quot;Comprueba actualizaciones&amp;quot;
IsBackgroundVisible=&amp;quot;False&amp;quot;
Click=&amp;quot;btnUpdate_Click&amp;quot;&amp;gt;
&amp;lt;/ThumbButtonInfo&amp;gt;
&amp;lt;ThumbButtonInfo x:Name=&amp;quot;btnClient&amp;quot;
ImageSource=&amp;quot;{StaticResource IconClient}&amp;quot;
Description=&amp;quot;Ver los clientes&amp;quot;
IsBackgroundVisible=&amp;quot;True&amp;quot;
Click=&amp;quot;btnClient_Click&amp;quot;&amp;gt;
&amp;lt;/ThumbButtonInfo&amp;gt;
&amp;lt;ThumbButtonInfo x:Name=&amp;quot;btnInvoice&amp;quot;
ImageSource=&amp;quot;{StaticResource IconInvoice}&amp;quot;
Description=&amp;quot;Ver las facturas&amp;quot;
IsBackgroundVisible=&amp;quot;True&amp;quot;
IsEnabled=&amp;quot;False&amp;quot;
Click=&amp;quot;btnInvoice_Click&amp;quot;&amp;gt;
&amp;lt;/ThumbButtonInfo&amp;gt;&lt;/pre&gt;
&lt;p&gt;Como veis en cada bot&amp;oacute;n hemos a&amp;ntilde;adido un evento Click, ahora en c&amp;oacute;digo escribimos el c&amp;oacute;digo necesario en cada manejador de eventos: &lt;/p&gt;
&lt;pre class="brush: vb;"&gt;Private Sub btnUpdate_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
MessageBox.Show(&amp;quot;Click en actualizar mediante eventos&amp;quot;)
End Sub

Private Sub btnClient_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
MessageBox.Show(&amp;quot;Click en clientes mediante eventos&amp;quot;)
End Sub

Private Sub btnInvoice_Click(ByVal sender As System.Object, ByVal e As System.EventArgs)
MessageBox.Show(&amp;quot;Click en facturas mediante eventos&amp;quot;)
End Sub&lt;/pre&gt;
&lt;p&gt;Con esto si volvemos a ejecutar nuestra aplicaci&amp;oacute;n y pulsamos sobre los botones aparecer&amp;aacute; el messagebox que corresponda: &lt;/p&gt;
&lt;div align="center"&gt;&lt;a href="http://lh3.ggpht.com/_7YCdMP8inuc/TFhI1JF2knI/AAAAAAAAAGs/OhjTLDUXrx8/s1600-h/Toolbar2%5B6%5D.png"&gt;&lt;img height="374" width="549" src="http://lh3.ggpht.com/_7YCdMP8inuc/TFhI3MjO4zI/AAAAAAAAAGw/L5znU6w2JbI/Toolbar2_thumb%5B4%5D.png?imgmax=800" alt="Toolbar2" border="0" title="Toolbar2" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;h4&gt;Usando Comandos&lt;/h4&gt;
&lt;p&gt;Este m&amp;eacute;todo conlleva un poco m&amp;aacute;s de trabajo, pero es mucho m&amp;aacute;s representativo de lo que una aplicaci&amp;oacute;n seria deber&amp;iacute;a hacer. El primer paso es crear una clase nueva clase para cada bot&amp;oacute;n: &lt;/p&gt;
&lt;div align="center"&gt;&lt;a href="http://lh5.ggpht.com/_7YCdMP8inuc/TFhI3i2yBTI/AAAAAAAAAG0/ulCtcdLOm90/s1600-h/comandos1%5B7%5D.png"&gt;&lt;img height="241" width="248" src="http://lh5.ggpht.com/_7YCdMP8inuc/TFhI4065lbI/AAAAAAAAAG4/rxBLmv7fKfo/comandos1_thumb%5B5%5D.png?imgmax=800" alt="comandos1" border="0" title="comandos1" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;p&gt;Como pod&amp;eacute;is ver hemos creado una clase para cada acci&amp;oacute;n que queremos realizar: Client, Invoice y Update, estas clases deben implementar el Interface ICommand para que se puedan usar como comandos en nuestra aplicaci&amp;oacute;n: &lt;/p&gt;
&lt;pre class="brush: vb;"&gt;&amp;#39;UpdateCommand.vb
Public Class UpdateCommand
Implements ICommand

Public Function CanExecute(ByVal parameter As Object) As Boolean Implements System.Windows.Input.ICommand.CanExecute
&amp;#39;Aqu&amp;iacute; c&amp;oacute;digo para comprobar si tu comando puede ejecutarse.
Return True
End Function

Public Event CanExecuteChanged(ByVal sender As Object, ByVal e As System.EventArgs) Implements System.Windows.Input.ICommand.CanExecuteChanged

Public Sub Execute(ByVal parameter As Object) Implements System.Windows.Input.ICommand.Execute
MessageBox.Show(&amp;quot;Click en actualizar mediante comandos&amp;quot;)
End Sub
End Class

&amp;#39;ClientCommand.vb
Public Class ClientCommand
Implements ICommand

Public Function CanExecute(ByVal parameter As Object) As Boolean Implements System.Windows.Input.ICommand.CanExecute
&amp;#39;Aqu&amp;iacute; c&amp;oacute;digo para comprobar si tu comando puede ejecutarse.
Return True
End Function

Public Event CanExecuteChanged(ByVal sender As Object, ByVal e As System.EventArgs) Implements System.Windows.Input.ICommand.CanExecuteChanged

Public Sub Execute(ByVal parameter As Object) Implements System.Windows.Input.ICommand.Execute
MessageBox.Show(&amp;quot;Click en clientes mediante comandos&amp;quot;)
End Sub
End Class

&amp;#39;InvoiceCommand.vb
Public Class InvoiceCommand
Implements ICommand

Public Function CanExecute(ByVal parameter As Object) As Boolean Implements System.Windows.Input.ICommand.CanExecute
&amp;#39;Aqu&amp;iacute; c&amp;oacute;digo para comprobar si tu comando puede ejecutarse.
Return True
End Function

Public Event CanExecuteChanged(ByVal sender As Object, ByVal e As System.EventArgs) Implements System.Windows.Input.ICommand.CanExecuteChanged

Public Sub Execute(ByVal parameter As Object) Implements System.Windows.Input.ICommand.Execute
MessageBox.Show(&amp;quot;Click en facturas mediante comandos&amp;quot;)
End Sub
End Class&lt;/pre&gt;
&lt;div align="justify"&gt;Los Comandos son muy &amp;uacute;tiles y una muy buena forma de distribuir el c&amp;oacute;digo de tu aplicaci&amp;oacute;n, te recomiendo que eches un vistazo a estos v&amp;iacute;deos que explican mucho m&amp;aacute;s a fondo el uso de comandos:&lt;/div&gt;
&lt;p&gt;&lt;a target="_blank" href="http://windowsclient.net/learn/video.aspx?v=288066"&gt;How Do I: Use Command Binding in WPF&lt;/a&gt; &lt;a target="_blank" href="http://windowsclient.net/learn/video.aspx?v=292642"&gt;How Do I: Create a Custom Command in WPF&lt;/a&gt;&lt;/p&gt;
&lt;div align="justify"&gt;Lo siguiente que necesitamos hacer es tener un lugar com&amp;uacute;n desde el que exponer nuestros comandos, para esto podemos usar el ViewModel, a&amp;ntilde;ade un nuevo archivo de clase a tu proyecto, ll&amp;aacute;malo ViewModel y ponle el siguiente c&amp;oacute;digo:&lt;/div&gt;
&lt;pre class="brush: vb;"&gt;Public Class ViewModel
Private _UpdateCommand As UpdateCommand = New UpdateCommand()
Private _ClientCommand As ClientCommand = New ClientCommand()
Private _InvoiceCommand As InvoiceCommand = New InvoiceCommand()

Public ReadOnly Property UpdateCommand As ICommand
Get
Return _UpdateCommand
End Get
End Property

Public ReadOnly Property ClientCommand As ICommand
Get
Return _ClientCommand
End Get
End Property

Public ReadOnly Property InvoiceCommand As ICommand
Get
Return _InvoiceCommand
End Get
End Property
End Class&lt;/pre&gt;
&lt;p&gt;Nuestro ViewModel simplemente expone propiedades p&amp;uacute;blicas del tipo de nuestros comandos hacia la capa de Visualizaci&amp;oacute;n, el Xaml en este caso, por lo que solo debemos referenciar en nuestro Xaml este ViewModel en nuestro DataContext: &lt;/p&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Window x:Class=&amp;quot;MainWindow&amp;quot;
xmlns=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;
xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;
xmlns:viewModel=&amp;quot;clr-namespace:WPF_JumpList_And_Thumbnail_Toolbars&amp;quot;
Title=&amp;quot;MainWindow&amp;quot; Height=&amp;quot;350&amp;quot; Width=&amp;quot;525&amp;quot;&amp;gt;

&amp;lt;Window.DataContext&amp;gt;
&amp;lt;viewModel:ViewModel&amp;gt;&amp;lt;/viewModel:ViewModel&amp;gt;
&amp;lt;/Window.DataContext&amp;gt;

&amp;lt;/Window&amp;gt;&lt;/pre&gt;
&lt;p&gt;Por &amp;uacute;ltimo ya solo nos queda enlazar nuestros botones con sus respectivos comandos, para esto usaremos la propiedad Command de cada ThumbButtonInfo: &lt;/p&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ThumbButtonInfo x:Name=&amp;quot;btnUpdate&amp;quot;
ImageSource=&amp;quot;{StaticResource IconUpdate}&amp;quot;
Description=&amp;quot;Comprueba actualizaciones&amp;quot;
IsBackgroundVisible=&amp;quot;True&amp;quot;
Command=&amp;quot;{Binding UpdateCommand}&amp;quot;&amp;gt;
&amp;lt;/ThumbButtonInfo&amp;gt;
&amp;lt;ThumbButtonInfo x:Name=&amp;quot;btnClient&amp;quot;
ImageSource=&amp;quot;{StaticResource IconClient}&amp;quot;
Description=&amp;quot;Ver los clientes&amp;quot;
IsBackgroundVisible=&amp;quot;True&amp;quot;
Command=&amp;quot;{Binding ClientCommand}&amp;quot;&amp;gt;
&amp;lt;/ThumbButtonInfo&amp;gt;
&amp;lt;ThumbButtonInfo x:Name=&amp;quot;btnInvoice&amp;quot;
ImageSource=&amp;quot;{StaticResource IconInvoice}&amp;quot;
Description=&amp;quot;Ver las facturas&amp;quot;
IsBackgroundVisible=&amp;quot;True&amp;quot;
Command=&amp;quot;{Binding InvoiceCommnad}&amp;quot;&amp;gt;
&amp;lt;/ThumbButtonInfo&amp;gt;&lt;/pre&gt;
&lt;p&gt;Como pod&amp;eacute;is ver simplemente hacemos un Binding a nuestro comando. Si ejecut&amp;aacute;is la aplicaci&amp;oacute;n de nuevo y presion&amp;aacute;is sobre un bot&amp;oacute;n ver&amp;eacute;is que el efecto es el mismo que con los eventos, solo que en esta ocasi&amp;oacute;n nuestro c&amp;oacute;digo es mucho m&amp;aacute;s reutilizable y est&amp;aacute; m&amp;aacute;s ordenado, pudiendo compartir entre varias ventanas o controles el mismo comando y conservando la misma funcionalidad: &lt;/p&gt;
&lt;div align="center"&gt;&lt;a href="http://lh6.ggpht.com/_7YCdMP8inuc/TFhI6Seso-I/AAAAAAAAAG8/7Yo_dSFy33M/s1600-h/comandos2%5B5%5D.png"&gt;&lt;img height="375" width="552" src="http://lh3.ggpht.com/_7YCdMP8inuc/TFhI7lz8xoI/AAAAAAAAAHA/7RmytKt3wy4/comandos2_thumb%5B3%5D.png?imgmax=800" alt="comandos2" border="0" title="comandos2" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;&lt;/div&gt;
&lt;p&gt;Y esto es todo. Tras esta serie de art&amp;iacute;culos ya sab&amp;eacute;is todo lo necesario para hacer a vuestra aplicaci&amp;oacute;n m&amp;aacute;s &amp;quot;Windows7 Friendly&amp;rdquo; y, lo m&amp;aacute;s importante, m&amp;aacute;s intuitiva, sencilla y &amp;uacute;til para vuestros usuarios. &lt;/p&gt;
&lt;div align="justify"&gt;Por si ten&amp;eacute;is alguna dificultad, a parte por supuesto de poder contactar conmigo tanto dejando mensajes como en mi twitter, como en msdn o a mi email directamente, os dejo el proyecto completo para descarga, junto con los estilos y control templates que he usado. &lt;/div&gt;
&lt;div align="justify"&gt;Y recordad, con un simple comentario, pod&amp;eacute;is hacer feliz a un peque&amp;ntilde;o bloguero :)&lt;/div&gt;
&lt;div align="justify"&gt;Muchas gracias por leerme y &lt;strong&gt;Happy Coding&lt;/strong&gt;!&lt;/div&gt;
&lt;p&gt;&lt;a href="http://cid-fd100135b82f3364.office.live.com/self.aspx/.Public/ejemplos/Integracion%20Win7/WPF%20JumpList%20And%20Thumbnail%20Toolbars/WPF%20JumpList%20And%20Thumbnail%20Toolbars.zip"&gt;Descargar c&amp;oacute;digo&lt;/a&gt;&lt;/p&gt;</description></item><item><title>WPF: Integrando nuestra aplicación con la Barra de Tareas de Windows 7 (I)</title><link>http://geeks.ms/wikis/wpf/wpf-integrando-nuestra-aplicaci-243-n-con-la-barra-de-tareas-de-windows-7-i/revision/0.aspx</link><pubDate>Mon, 26 Jul 2010 04:41:36 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:10</guid><dc:creator>Josué Yeray Julián Ferreiro</dc:creator><description>Revisión actual enviado a Wiki sobre WPF en Geeks•ms por Josué Yeray Julián Ferreiro a 7/26/2010 6:41:36 AM&lt;br /&gt;
&lt;div align="justify"&gt;Hola a todos!&lt;/div&gt;
&lt;div align="justify"&gt;En el &amp;uacute;ltimo art&amp;iacute;culo, hablamos de lo importante que es aprovechar las caracter&amp;iacute;sticas que nos ofrece el S.O. sobre el que nuestra aplicaci&amp;oacute;n se ejecuta, vimos como integrar nuestra aplicaci&amp;oacute;n con el sistema de energ&amp;iacute;a de Windows 7 para hacerla &amp;ldquo;amigable&amp;rdquo; con el consumo.&lt;/div&gt;
&lt;div align="justify"&gt;Esta vez vamos a hablar de la barra de tareas de Windows 7, fue uno de los grandes cambios en el sistema operativo, y trae muchas ventajas&amp;nbsp; para facilitar la comunicaci&amp;oacute;n r&amp;aacute;pida e intuitiva entre nuestra aplicaci&amp;oacute;n y nuestros usuarios:&lt;/div&gt;
&lt;!--more--&gt;&lt;ol&gt;
&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;IconOverlay:&lt;/strong&gt; Esta propiedad de la barra de tareas nos permite colocar desde nuestro c&amp;oacute;digo un peque&amp;ntilde;o icono de 16x16 sobre el icono de nuestra aplicaci&amp;oacute;n, en la esquina inferior derecha, con lo que podemos avisar a nuestro usuario de cambios en el estado de la aplicaci&amp;oacute;n sin que tenga la pantalla mostrandose.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;ProgressBar:&lt;/strong&gt; Muy util sin duda, nos permite colocar bajo el icono de nuestra aplicaci&amp;oacute;n una barra de progreso, con m&amp;uacute;ltiples estados, capaz de comunicar a nuestro usuario el estado y progreso de una determinada tarea mientras usa otras aplicaciones, consiguiendo maximizar la productividad.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;Jumplist:&lt;/strong&gt; Las Jumplist son enlaces r&amp;aacute;pidos a partes de nuestra aplicaci&amp;oacute;n que aparecen al hacer click derecho sobre el icono de la misma en la barra de tareas, podemos hacer que nuestra app vaya directamente a una ventana en concreto, sin haberla arrancado todav&amp;iacute;a.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;Thumbnail Toolbars:&lt;/strong&gt; al pasar el rat&amp;oacute;n sobre los iconos de aplicaciones activas, Windows 7 nos ofrece una preview de la ventana de esa aplicaci&amp;oacute;n, con las Thumbnail Toolbars podemos a&amp;ntilde;adir botones a esa vista que ejecuten ordenes en nuestra aplicaci&amp;oacute;n.&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div align="justify"&gt;En este art&amp;iacute;culo vamos a centrarnos en las dos primeras: IconOverlay y ProgressBar, dejando las restantes para otro art&amp;iacute;culo.&lt;/div&gt;
&lt;h4&gt;.NET 3.5 vs .NET 4&lt;/h4&gt;
&lt;div align="justify"&gt;Para acceder a todas estas caracter&amp;iacute;sticas en .NET 3.5 solo ten&amp;iacute;amos un camino: Interoperabilidad con el api no manejada de Win32 (al igual que con el art&amp;iacute;culo sobre la gesti&amp;oacute;n de energ&amp;iacute;a), sin embargo para .NET 4 han integrado las funcionalidades de la barra de tareas de Windows 7 en el propio framework, por lo que el &amp;ldquo;uso y disfrute&amp;rdquo; de estas caracter&amp;iacute;sticas es much&amp;iacute;simo m&amp;aacute;s sencillo. Por ello el c&amp;oacute;digo de este art&amp;iacute;culo es solo &amp;uacute;til para .NET 4.&lt;/div&gt;
&lt;h4&gt;Empecemos&lt;/h4&gt;
&lt;div align="justify"&gt;Primero y como ya es costumbre, una imagen vale m&amp;aacute;s que mil palabras, pues esta vez tenemos dos:&lt;/div&gt;
&lt;div align="center"&gt;&lt;a href="http://lh3.ggpht.com/_7YCdMP8inuc/TEq6-MXY07I/AAAAAAAAAFA/OIMJ-9ntbY8/s1600-h/Tab001%5B3%5D.png"&gt;&lt;img height="216" width="240" src="http://lh4.ggpht.com/_7YCdMP8inuc/TEq6_7UOiyI/AAAAAAAAAFE/RlNF5Y9WJKk/Tab001_thumb%5B1%5D.png?imgmax=800" alt="Tab001" border="0" title="Tab001" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;a href="http://lh5.ggpht.com/_7YCdMP8inuc/TEq7Ch80XwI/AAAAAAAAAFI/5qr-_DSQDGY/s1600-h/tab002%5B3%5D.png"&gt;&lt;img height="216" width="240" src="http://lh3.ggpht.com/_7YCdMP8inuc/TEq7EjsisGI/AAAAAAAAAFM/Pjo260ES6nY/tab002_thumb%5B1%5D.png?imgmax=800" alt="tab002" border="0" title="tab002" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;Como veis me he puesto en plan original con los iconos&amp;hellip;. y si, lo se, que yo me dedique al dise&amp;ntilde;o es tan da&amp;ntilde;ino como las armas de destrucci&amp;oacute;n masiva&amp;hellip;. pero por eso soy programador :)&lt;/div&gt;
&lt;div align="justify"&gt;Vamos a comenzar, lo primero es crear un nuevo proyecto WPF Application (File &amp;gt; New &amp;gt; Project), una vez creado, vamos a dise&amp;ntilde;ar la pantalla principal en el archivo MainWindow.xaml&lt;/div&gt;
&lt;div align="justify"&gt;Los estilos que he usado en esta aplicaci&amp;oacute;n est&amp;aacute;n disponibles en la descarga en el archivo Application.xaml, si ten&amp;eacute;is dudas acerca de como usar / crear estilos, echadle un vistazo a mis dos art&amp;iacute;culos sobre este tema: &lt;a target="_blank" href="http://jyeray.blogspot.com/2010/05/wpf-personalizar-nuestra-aplicacion-con.html"&gt;aqu&amp;iacute;&lt;/a&gt; y &lt;a target="_blank" href="http://jyeray.blogspot.com/2010/06/wpf-personalizar-nuestra-aplicacion-con.html"&gt;aqu&amp;iacute;&lt;/a&gt;&lt;/div&gt;
&lt;div align="justify"&gt;Bien, para empezar a trabajar con la barra de tareas debemos a&amp;ntilde;adir en xaml un objeto de tipo TaskbarItemInfo:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Window.TaskbarItemInfo&amp;gt;
&amp;lt;TaskbarItemInfo/&amp;gt;
&amp;lt;/Window.TaskbarItemInfo&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Con esto ya tendremos acceso a multitud de propiedades de la barra de tareas de windows 7 de forma sencilla y r&amp;aacute;pida.&amp;nbsp;&lt;/div&gt;
&lt;h4&gt;IconOverlay&lt;/h4&gt;
&lt;div style="text-align:center;"&gt;&lt;a href="http://lh6.ggpht.com/_7YCdMP8inuc/TEq7H4kYheI/AAAAAAAAAFQ/jbHLqkqbacM/s1600-h/Tab001%5B8%5D.png"&gt;&lt;img height="364" width="540" src="http://lh5.ggpht.com/_7YCdMP8inuc/TEq7Lf797PI/AAAAAAAAAFU/S2qY0lWxng0/Tab001_thumb%5B4%5D.png?imgmax=800" alt="Tab001" border="0" title="Tab001" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;Vamos a empezar a trabajar con los IconOverlay, lo primero que debemos hacer es a&amp;ntilde;adir como recurso en nuestro proyecto los archivos de im&amp;aacute;gen que queramos usar (png o ico por las transparencias).&lt;/div&gt;
&lt;div align="justify"&gt;Una vez hecho esto debemos crear un DrawingImage como recurso de nuestra ventana por cada im&amp;aacute;gen, en mi caso son 5:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Window.Resources&amp;gt;
&amp;lt;DrawingImage x:Key=&amp;quot;IconRed&amp;quot;&amp;gt;
&amp;lt;DrawingImage.Drawing&amp;gt;
&amp;lt;ImageDrawing Rect=&amp;quot;0,0,16,16&amp;quot; 
ImageSource=&amp;quot;/WPF%20Icon%20Overlay%20And%20ProgressBar;
component/images/FireToy.ico&amp;quot; /&amp;gt;
&amp;lt;/DrawingImage.Drawing&amp;gt;
&amp;lt;/DrawingImage&amp;gt;
&amp;lt;DrawingImage x:Key=&amp;quot;IconGreen&amp;quot;&amp;gt;
&amp;lt;DrawingImage.Drawing&amp;gt;
&amp;lt;ImageDrawing Rect=&amp;quot;0,0,16,16&amp;quot; 
ImageSource=&amp;quot;/WPF%20Icon%20Overlay%20And%20ProgressBar;
component/images/GreenToy.ico&amp;quot; /&amp;gt;
&amp;lt;/DrawingImage.Drawing&amp;gt;
&amp;lt;/DrawingImage&amp;gt;
&amp;lt;DrawingImage x:Key=&amp;quot;IconBlue&amp;quot;&amp;gt;
&amp;lt;DrawingImage.Drawing&amp;gt;
&amp;lt;ImageDrawing Rect=&amp;quot;0,0,16,16&amp;quot; 
ImageSource=&amp;quot;/WPF%20Icon%20Overlay%20And%20ProgressBar;
component/images/BlueToy.ico&amp;quot; /&amp;gt;
&amp;lt;/DrawingImage.Drawing&amp;gt;
&amp;lt;/DrawingImage&amp;gt;
&amp;lt;DrawingImage x:Key=&amp;quot;IconPink&amp;quot;&amp;gt;
&amp;lt;DrawingImage.Drawing&amp;gt;
&amp;lt;ImageDrawing Rect=&amp;quot;0,0,16,16&amp;quot; 
ImageSource=&amp;quot;/WPF%20Icon%20Overlay%20And%20ProgressBar;
component/images/PinkToy.ico&amp;quot; /&amp;gt;
&amp;lt;/DrawingImage.Drawing&amp;gt;
&amp;lt;/DrawingImage&amp;gt;
&amp;lt;DrawingImage x:Key=&amp;quot;IconBlack&amp;quot;&amp;gt;
&amp;lt;DrawingImage.Drawing&amp;gt;
&amp;lt;ImageDrawing Rect=&amp;quot;0,0,16,16&amp;quot; 
ImageSource=&amp;quot;/WPF%20Icon%20Overlay%20And%20ProgressBar;
component/images/NinjaToy.ico&amp;quot; /&amp;gt;
&amp;lt;/DrawingImage.Drawing&amp;gt;
&amp;lt;/DrawingImage&amp;gt;
&amp;lt;/Window.Resources&amp;gt;&lt;/pre&gt;
&lt;p&gt;Una vez hecho esto, vamos a crear el TabItem con los botones y dem&amp;aacute;s: &lt;/p&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;TabItem Header=&amp;quot;Taskbar IconOverlay&amp;quot; Name=&amp;quot;TabItem1&amp;quot;&amp;gt;
&amp;lt;Grid&amp;gt;
&amp;lt;Grid.Background&amp;gt;
&amp;lt;ImageBrush ImageSource=&amp;quot;pack://application:,,,/
WPF Icon Overlay And ProgressBar;
component/images/overlay.png&amp;quot; 
Stretch=&amp;quot;Uniform&amp;quot; Opacity=&amp;quot;.2&amp;quot; /&amp;gt;
&amp;lt;/Grid.Background&amp;gt;
&amp;lt;Grid.RowDefinitions&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;.33*&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;.33*&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;.33*&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;/Grid.RowDefinitions&amp;gt;
&amp;lt;Grid.ColumnDefinitions&amp;gt;
&amp;lt;ColumnDefinition Width=&amp;quot;.2*&amp;quot;&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
&amp;lt;ColumnDefinition Width=&amp;quot;.2*&amp;quot;&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
&amp;lt;ColumnDefinition Width=&amp;quot;.2*&amp;quot;&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
&amp;lt;ColumnDefinition Width=&amp;quot;.2*&amp;quot;&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
&amp;lt;ColumnDefinition Width=&amp;quot;.2*&amp;quot;&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
&amp;lt;/Grid.ColumnDefinitions&amp;gt;

&amp;lt;Label Grid.ColumnSpan=&amp;quot;5&amp;quot; Grid.Row=&amp;quot;0&amp;quot; VerticalContentAlignment=&amp;quot;Center&amp;quot; 
HorizontalContentAlignment=&amp;quot;Center&amp;quot; FontSize=&amp;quot;24&amp;quot; Foreground=&amp;quot;White&amp;quot;
Content=&amp;quot;Seleccione una imagen para superponer&amp;quot;&amp;gt;
&amp;lt;/Label&amp;gt;

&amp;lt;Button Grid.Column=&amp;quot;0&amp;quot; Grid.Row=&amp;quot;1&amp;quot; Name=&amp;quot;btnIconRed&amp;quot; Width=&amp;quot;64&amp;quot; Height=&amp;quot;64&amp;quot; 
Padding=&amp;quot;0&amp;quot;&amp;gt;
&amp;lt;Button.Content&amp;gt;
&amp;lt;Image Source=&amp;quot;{StaticResource IconRed}&amp;quot; Width=&amp;quot;56&amp;quot; Height=&amp;quot;56&amp;quot; 
Stretch=&amp;quot;Uniform&amp;quot; Margin=&amp;quot;0&amp;quot;&amp;gt;&amp;lt;/Image&amp;gt;
&amp;lt;/Button.Content&amp;gt;
&amp;lt;/Button&amp;gt;
&amp;lt;Button Grid.Column=&amp;quot;1&amp;quot; Grid.Row=&amp;quot;1&amp;quot; Name=&amp;quot;btnIconGreen&amp;quot; Width=&amp;quot;64&amp;quot; Height=&amp;quot;64&amp;quot; 
Padding=&amp;quot;0&amp;quot;&amp;gt;
&amp;lt;Button.Content&amp;gt;
&amp;lt;Image Source=&amp;quot;{StaticResource IconGreen}&amp;quot; Width=&amp;quot;56&amp;quot; Height=&amp;quot;56&amp;quot; 
Stretch=&amp;quot;Uniform&amp;quot; Margin=&amp;quot;0&amp;quot;&amp;gt;&amp;lt;/Image&amp;gt;
&amp;lt;/Button.Content&amp;gt;
&amp;lt;/Button&amp;gt;
&amp;lt;Button Grid.Column=&amp;quot;2&amp;quot; Grid.Row=&amp;quot;1&amp;quot; Name=&amp;quot;btnIconBlue&amp;quot; Width=&amp;quot;64&amp;quot; Height=&amp;quot;64&amp;quot; 
Padding=&amp;quot;0&amp;quot;&amp;gt;
&amp;lt;Button.Content&amp;gt;
&amp;lt;Image Source=&amp;quot;{StaticResource IconBlue}&amp;quot; Width=&amp;quot;56&amp;quot; Height=&amp;quot;56&amp;quot; 
Stretch=&amp;quot;Uniform&amp;quot; Margin=&amp;quot;0&amp;quot;&amp;gt;&amp;lt;/Image&amp;gt;
&amp;lt;/Button.Content&amp;gt;
&amp;lt;/Button&amp;gt;
&amp;lt;Button Grid.Column=&amp;quot;3&amp;quot; Grid.Row=&amp;quot;1&amp;quot; Name=&amp;quot;btnIconPink&amp;quot; Width=&amp;quot;64&amp;quot; Height=&amp;quot;64&amp;quot; 
Padding=&amp;quot;0&amp;quot;&amp;gt;
&amp;lt;Button.Content&amp;gt;
&amp;lt;Image Source=&amp;quot;{StaticResource IconPink}&amp;quot; Width=&amp;quot;56&amp;quot; Height=&amp;quot;56&amp;quot; 
Stretch=&amp;quot;Uniform&amp;quot; Margin=&amp;quot;0&amp;quot;&amp;gt;&amp;lt;/Image&amp;gt;
&amp;lt;/Button.Content&amp;gt;
&amp;lt;/Button&amp;gt;
&amp;lt;Button Grid.Column=&amp;quot;4&amp;quot; Grid.Row=&amp;quot;1&amp;quot; Name=&amp;quot;btnIconBlack&amp;quot; Width=&amp;quot;64&amp;quot; Height=&amp;quot;64&amp;quot; 
Padding=&amp;quot;0&amp;quot;&amp;gt;
&amp;lt;Button.Content&amp;gt;
&amp;lt;Image Source=&amp;quot;{StaticResource IconBlack}&amp;quot; Width=&amp;quot;56&amp;quot; Height=&amp;quot;56&amp;quot; 
Stretch=&amp;quot;Uniform&amp;quot; Margin=&amp;quot;0&amp;quot;&amp;gt;&amp;lt;/Image&amp;gt;
&amp;lt;/Button.Content&amp;gt;
&amp;lt;/Button&amp;gt;                    

&amp;lt;Button Grid.ColumnSpan=&amp;quot;5&amp;quot; Grid.Row=&amp;quot;2&amp;quot; Name=&amp;quot;btnIconReset&amp;quot; Width=&amp;quot;125&amp;quot; 
Height=&amp;quot;30&amp;quot; Content=&amp;quot;Reset Overlay&amp;quot;&amp;gt;&amp;lt;/Button&amp;gt;
&amp;lt;/Grid&amp;gt;
&amp;lt;/TabItem&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Ya hemos terminado con todo el c&amp;oacute;digo xaml necesario para el IconOverlay, ahora vamos a por el c&amp;oacute;digo, lo primero es iniciar, en el evento Loaded de nuestra Window , el estado del IconOverlay a ninguno:&lt;/div&gt;
&lt;pre class="brush: vb;"&gt;#Region &amp;quot;Window Code&amp;quot;
Private Sub MainWindow_Loaded(ByVal sender As Object, 
ByVal e As System.Windows.RoutedEventArgs) 
Handles Me.Loaded
Me.TaskbarItemInfo.Overlay = Nothing
End Sub
#End Region&lt;/pre&gt;
&lt;div align="justify"&gt;Como ves, acceder a las propiedades del icono de nuestra aplicaci&amp;oacute;n en la barra de tareas es muy sencillo gracias al objeto TaskbarItemInfo que hemos creado en Xaml.&lt;/div&gt;
&lt;div align="justify"&gt;En este caso asignando Nothing le indicamos que no tiene ning&amp;uacute;n icono asociado.&lt;/div&gt;
&lt;div align="justify"&gt;Ahora, en el evento Click de cada bot&amp;oacute;n vamos a establecer el icono asociado al bot&amp;oacute;n como el icono a colocar sobre la barra de tareas:&lt;/div&gt;
&lt;pre class="brush: vb;"&gt;#Region &amp;quot;Taskbar IconOverlay&amp;quot;
Private Sub btnIconBlack_Click(ByVal sender As Object, 
ByVal e As System.Windows.RoutedEventArgs) 
Handles btnIconBlack.Click
Me.TaskbarItemInfo.Overlay = CType(Resources(&amp;quot;IconBlack&amp;quot;), ImageSource)
End Sub

Private Sub btnIconBlue_Click(ByVal sender As Object, 
ByVal e As System.Windows.RoutedEventArgs) 
Handles btnIconBlue.Click
Me.TaskbarItemInfo.Overlay = CType(Resources(&amp;quot;IconBlue&amp;quot;), ImageSource)
End Sub

Private Sub btnIconGreen_Click(ByVal sender As Object, 
ByVal e As System.Windows.RoutedEventArgs) 
Handles btnIconGreen.Click
Me.TaskbarItemInfo.Overlay = CType(Resources(&amp;quot;IconGreen&amp;quot;), ImageSource)
End Sub

Private Sub btnIconPink_Click(ByVal sender As Object, 
ByVal e As System.Windows.RoutedEventArgs) 
Handles btnIconPink.Click
Me.TaskbarItemInfo.Overlay = CType(Resources(&amp;quot;IconPink&amp;quot;), ImageSource)
End Sub

Private Sub btnIconRed_Click(ByVal sender As Object, 
ByVal e As System.Windows.RoutedEventArgs) 
Handles btnIconRed.Click
Me.TaskbarItemInfo.Overlay = CType(Resources(&amp;quot;IconRed&amp;quot;), ImageSource)
End Sub

Private Sub btnIconReset_Click(ByVal sender As Object, 
ByVal e As System.Windows.RoutedEventArgs) 
Handles btnIconReset.Click
Me.TaskbarItemInfo.Overlay = Nothing
End Sub
#End Region&lt;/pre&gt;
&lt;div align="justify"&gt;Bueno, no es muy complicado &amp;iquest;no? Al principio del art&amp;iacute;culo creamos unos recursos de la ventana que eran del tipo DrawingImage, simplemente lo que hacemos en este c&amp;oacute;digo es convertir estos recursos al tipo ImageSource, que es el que espera la propiedad Overlay del objeto TaskbarItemInfo y asignarlos, el resultado es inmediato, si presionamos el bot&amp;oacute;n que tiene asociado el avatar de fuego este ser&amp;aacute; el resultado:&lt;/div&gt;
&lt;div align="center"&gt;&lt;a href="http://lh5.ggpht.com/_7YCdMP8inuc/TEq7MInmIpI/AAAAAAAAAFY/hEIngO7tNKo/s1600-h/taskbar%20icon%5B3%5D.png"&gt;&lt;img height="55" width="63" src="http://lh5.ggpht.com/_7YCdMP8inuc/TEq7M1SHqHI/AAAAAAAAAFc/34D4trMZdFE/taskbar%20icon_thumb%5B1%5D.png?imgmax=800" alt="taskbar icon" border="0" title="taskbar icon" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;Y si presionamos el bot&amp;oacute;n Reset Overlay volver&amp;aacute; a su estado normal:&lt;/div&gt;
&lt;div align="center"&gt;&lt;a href="http://lh5.ggpht.com/_7YCdMP8inuc/TEq7NTnVCaI/AAAAAAAAAFg/TVDEHyE-9go/s1600-h/taskbar%20no%20icon%5B3%5D.png"&gt;&lt;img height="53" width="63" src="http://lh4.ggpht.com/_7YCdMP8inuc/TEq7O8UunQI/AAAAAAAAAFk/lCmBXmVKvXg/taskbar%20no%20icon_thumb%5B1%5D.png?imgmax=800" alt="taskbar no icon" border="0" title="taskbar no icon" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;Como veis es un c&amp;oacute;digo muy sencillo y que nos abre nuevas v&amp;iacute;as de comunicaci&amp;oacute;n con nuestros usuarios, podr&amp;iacute;amos por ejemplo mostrar un icono cuando se ha producido un error, si se require la intervenci&amp;oacute;n del usuario en una tarea o si hay nuevos datos, de esta forma nuestro usuario no depender&amp;iacute;a de estar viendo nuestra ventana para saber que pasa, podr&amp;iacute;a estar consultando el correo, trabajando en excel o simplemente viendo algunas p&amp;aacute;ginas de internet y se enterar&amp;iacute;a instant&amp;aacute;neamente de la necesidad de intervenir en nuestra aplicaci&amp;oacute;n.&lt;/div&gt;
&lt;h4&gt;ProgressBar&lt;/h4&gt;
&lt;div align="center"&gt;&lt;a href="http://lh3.ggpht.com/_7YCdMP8inuc/TEq7RUVvVxI/AAAAAAAAAFo/xW1wtDvXSOU/s1600-h/tab002%5B8%5D.png"&gt;&lt;img height="365" width="541" src="http://lh4.ggpht.com/_7YCdMP8inuc/TEq7UsAvIQI/AAAAAAAAAFw/jPMbwjWFbtQ/tab002_thumb%5B4%5D.png?imgmax=800" alt="tab002" border="0" title="tab002" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;Si el IconOverlay te ha parecido sencillo, el uso de la barra de progreso en el icono de la barra de tareas lo es m&amp;aacute;s, vamos a empezar dise&amp;ntilde;ando la pantalla:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;TabItem Header=&amp;quot;Taskbar ProgressBar&amp;quot; Name=&amp;quot;TabItem2&amp;quot;&amp;gt;
&amp;lt;Grid&amp;gt;
&amp;lt;Grid.Background&amp;gt;
&amp;lt;ImageBrush ImageSource=&amp;quot;pack://application:,,,/
WPF Icon Overlay And ProgressBar;
component/images/progressbar.png&amp;quot; 
Stretch=&amp;quot;Uniform&amp;quot; Opacity=&amp;quot;.2&amp;quot; /&amp;gt;
&amp;lt;/Grid.Background&amp;gt;
&amp;lt;Grid.RowDefinitions&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;.25*&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;.25*&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;.25*&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;.25*&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;/Grid.RowDefinitions&amp;gt;

&amp;lt;Label Grid.Row=&amp;quot;0&amp;quot; VerticalContentAlignment=&amp;quot;Center&amp;quot; 
HorizontalContentAlignment=&amp;quot;Center&amp;quot; FontSize=&amp;quot;24&amp;quot; Foreground=&amp;quot;White&amp;quot;
Content=&amp;quot;Mueve el Slider para Aumentar/Disminuir&amp;quot;&amp;gt;
&amp;lt;/Label&amp;gt;

&amp;lt;ComboBox Grid.Row=&amp;quot;1&amp;quot; Name=&amp;quot;cmbEstilos&amp;quot; Height=&amp;quot;30&amp;quot; Width=&amp;quot;Auto&amp;quot; Margin=&amp;quot;5&amp;quot; 
HorizontalAlignment=&amp;quot;Stretch&amp;quot; VerticalAlignment=&amp;quot;Stretch&amp;quot;&amp;gt;
&amp;lt;ComboBox.Items&amp;gt;
&amp;lt;ComboBoxItem Name=&amp;quot;ItemNormal&amp;quot; Content=&amp;quot;Normal&amp;quot;/&amp;gt;
&amp;lt;ComboBoxItem Name=&amp;quot;ItemError&amp;quot; Content=&amp;quot;Error&amp;quot;/&amp;gt;
&amp;lt;ComboBoxItem Name=&amp;quot;ItemStop&amp;quot; Content=&amp;quot;Stop&amp;quot;/&amp;gt;
&amp;lt;ComboBoxItem Name=&amp;quot;ItemIndeterminate&amp;quot; Content=&amp;quot;Indeterminado&amp;quot;/&amp;gt;
&amp;lt;ComboBoxItem Name=&amp;quot;ItemNone&amp;quot; Content=&amp;quot;Ninguno&amp;quot;/&amp;gt;
&amp;lt;/ComboBox.Items&amp;gt;
&amp;lt;/ComboBox&amp;gt;

&amp;lt;ProgressBar Grid.Row=&amp;quot;2&amp;quot; Name=&amp;quot;Pbar&amp;quot; Height=&amp;quot;30&amp;quot; Width=&amp;quot;Auto&amp;quot; Margin=&amp;quot;5&amp;quot; 
HorizontalAlignment=&amp;quot;Stretch&amp;quot; VerticalAlignment=&amp;quot;Center&amp;quot;
Minimum=&amp;quot;0&amp;quot; Maximum=&amp;quot;100&amp;quot; 
Value=&amp;quot;{Binding Path=Value, ElementName=SlidValue}&amp;quot;&amp;gt;&amp;lt;/ProgressBar&amp;gt;

&amp;lt;Slider Grid.Row=&amp;quot;3&amp;quot; Name=&amp;quot;SlidValue&amp;quot; Height=&amp;quot;30&amp;quot; Width=&amp;quot;Auto&amp;quot; Margin=&amp;quot;5&amp;quot; 
HorizontalAlignment=&amp;quot;Stretch&amp;quot; VerticalAlignment=&amp;quot;Center&amp;quot; 
Minimum=&amp;quot;0&amp;quot; Maximum=&amp;quot;100&amp;quot; Value=&amp;quot;50&amp;quot; SmallChange=&amp;quot;1&amp;quot;&amp;gt;
&amp;lt;/Slider&amp;gt;
&amp;lt;/Grid&amp;gt;
&amp;lt;/TabItem&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;El c&amp;oacute;digo Xaml es muy sencillo, quiz&amp;aacute;s lo m&amp;aacute;s remarcable, y muy &amp;uacute;til, es el Binding que le he aplicado a la propiedad Value de la progressBar, este binding apunta hacia la propiedad Value del control Slider, de esta forma, cada ver que movamos el Slider autom&amp;aacute;ticamente se mover&amp;aacute; la barra de progreso.&lt;/div&gt;
&lt;div align="justify"&gt;Como veis existe un Combo con varias opciones, estos son los estados que puede tener la barra de progreso en la barra de tareas:&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;Normal:&lt;/strong&gt; La barra de progreso aparece de forma normal, en color verde.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;Error:&lt;/strong&gt; Igual que la normal, solo que el color de esta es rojo.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;Stop:&lt;/strong&gt; La barra de progreso esta parada y no puede avanzar, el color es amarillo.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;Indeterminate:&lt;/strong&gt; La barra no tiene un progreso determinado, hace una animaci&amp;oacute;n ciclica.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;&lt;strong&gt;None:&lt;/strong&gt; No se muestra la barra de progreso.&lt;/div&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;div align="justify"&gt;Si os pon&amp;eacute;is a pensar, seguro que ya se os est&amp;aacute;n ocurriendo mil usos&amp;hellip; un proceso largo en background que pueda tardar varios minutos, el usuario puede minimizar la aplicaci&amp;oacute;n y ver el progreso y resultado sin maximizarla, mientras trabaja en otra aplicaci&amp;oacute;n, puede ver cuando la tarea se ha detenido y necesita su atenci&amp;oacute;n (barra amarilla) cuando se ha producido un error (barra roja) o simplemente el progreso de la tarea, para ver si le da tiempo a tomar un cafe :), si combinamos esto con los IconOverlay, &amp;iquest;os dais cuenta de la potencia que obtenemos de comunicaci&amp;oacute;n con nuestro usuario? Podemos hacerle conocer el estado de nuestra aplicaci&amp;oacute;n sin ni siquiera maximizar la ventana, mientras est&amp;aacute; haciendo otras cosas, se acabaron los tiempos muertos.&lt;/div&gt;
&lt;div align="justify"&gt;El c&amp;oacute;digo tambi&amp;eacute;n es muy sencillo, en el evento Loaded establecemos la barra de progreso a None:&lt;/div&gt;
&lt;pre class="brush: vb;"&gt;#Region &amp;quot;Window Code&amp;quot;
Private Sub MainWindow_Loaded(ByVal sender As Object, 
ByVal e As System.Windows.RoutedEventArgs) 
Handles Me.Loaded
Me.TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.None
End Sub
#End Region&lt;/pre&gt;
&lt;div align="justify"&gt;Y ahora controlamos el evento ValueChanged del control Slider para asignar el valor a nuestra barra de progreso en la barra de tareas:&lt;/div&gt;
&lt;pre class="brush: vb;"&gt;Private Sub SlidValue_ValueChanged(ByVal sender As Object, 
ByVal e As System.Windows.RoutedPropertyChangedEventArgs(Of Double)) 
Handles SlidValue.ValueChanged
Me.TaskbarItemInfo.ProgressValue = SlidValue.Value / 100
End Sub&lt;/pre&gt;
&lt;div align="justify"&gt;Dos cosas aqu&amp;iacute;, primero, no es necesario tener una progressbar en nuestra ventana para que funcione la progressbar de la barra de tareas, pero creo que es necesario de cara al usuario tener ambos m&amp;eacute;todos, para no obligarle a tener que mirar la barra de tareas si est&amp;aacute; viendo nuestra ventana. Segundo, la propiedad ProgressValue del objeto TaskbarItemInfo tiene un rango de 1 a 0, por lo que debemos dividir el valor de nuestro control Slider o nuestro progreso entre 100 y siempre mantener valores entre 0 y 100 para no tener problemas.&lt;/div&gt;
&lt;div align="justify"&gt;Por &amp;uacute;ltimo vamos a controlar el evento SelectionChanged del combobox para cambiar nuestro tipo de barra de progreso al indicado en el desplegable:&lt;/div&gt;
&lt;pre class="brush: vb;"&gt;Private Sub combo_SelectionChanged(ByVal sender As Object, 
ByVal e As System.Windows.Controls.SelectionChangedEventArgs) 
Handles cmbEstilos.SelectionChanged

Select Case DirectCast(e.AddedItems(0), System.Windows.Controls.ComboBoxItem).Content
Case &amp;quot;Normal&amp;quot;
SlidValue.IsEnabled = True
Pbar.IsIndeterminate = False
Me.TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Normal
Case &amp;quot;Error&amp;quot;
SlidValue.IsEnabled = True
Pbar.IsIndeterminate = False
Me.TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Error
Case &amp;quot;Stop&amp;quot;
SlidValue.IsEnabled = True
Pbar.IsIndeterminate = False
Me.TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Paused
Case &amp;quot;Indeterminado&amp;quot;
SlidValue.IsEnabled = False
Pbar.IsIndeterminate = True
Me.TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.Indeterminate
Case &amp;quot;Ninguno&amp;quot;
SlidValue.IsEnabled = True
Pbar.IsIndeterminate = False
Me.TaskbarItemInfo.ProgressState = Shell.TaskbarItemProgressState.None
End Select
End Sub&lt;/pre&gt;
&lt;p&gt;Y con esto nuestra aplicaci&amp;oacute;n ya ser&amp;aacute; capaz de mostrar la barra de progreso en sus diferentes estilos: &lt;/p&gt;
&lt;div align="center"&gt;&lt;a href="http://lh5.ggpht.com/_7YCdMP8inuc/TEq7Vvak_9I/AAAAAAAAAF0/AI4vBjAR1tE/s1600-h/pbar%20normal%5B3%5D.png"&gt;&lt;img height="53" width="65" src="http://lh3.ggpht.com/_7YCdMP8inuc/TEq7WpLGY2I/AAAAAAAAAF4/3-aBV0718-U/pbar%20normal_thumb%5B1%5D.png?imgmax=800" alt="Normal" border="0" title="Normal" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;a href="http://lh3.ggpht.com/_7YCdMP8inuc/TEq7XoiOQFI/AAAAAAAAAF8/wF2xD_Htpf8/s1600-h/pbar%20error%5B3%5D.png"&gt;&lt;img height="53" width="67" src="http://lh4.ggpht.com/_7YCdMP8inuc/TEq7btEHISI/AAAAAAAAAGA/3TP1NmfsG3k/pbar%20error_thumb%5B1%5D.png?imgmax=800" alt="Error" border="0" title="Error" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;a href="http://lh5.ggpht.com/_7YCdMP8inuc/TEq7c6xPs-I/AAAAAAAAAGE/nav1rPW0JVc/s1600-h/pbar%20stop%5B3%5D.png"&gt;&lt;img height="53" width="67" src="http://lh4.ggpht.com/_7YCdMP8inuc/TEq7dt6bBEI/AAAAAAAAAGI/7xujNF3lUwY/pbar%20stop_thumb%5B1%5D.png?imgmax=800" alt="Pausa" border="0" title="Pausa" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;a href="http://lh6.ggpht.com/_7YCdMP8inuc/TEq7eAYbZVI/AAAAAAAAAGM/K_RE9-7wVuc/s1600-h/pbar%20indeterminate%5B3%5D.png"&gt;&lt;img height="53" width="67" src="http://lh4.ggpht.com/_7YCdMP8inuc/TEq7fLUtZGI/AAAAAAAAAGQ/45GrnVQKJsQ/pbar%20indeterminate_thumb%5B1%5D.png?imgmax=800" alt="Indeterminado" border="0" title="Indeterminado" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;Bueno, esto es todo por hoy, como pod&amp;eacute;is ver es un tema apasionante que nos abre nuevas alternativas de comunicaci&amp;oacute;n con el usuario, as&amp;iacute; que es nuestra obligaci&amp;oacute;n aprovecharlas, en el pr&amp;oacute;ximo art&amp;iacute;culo hablaremos de las Jumplist y los Thumbnail Toolbars, como nuevas formas de interactuar con nuestra aplicaci&amp;oacute;n.&lt;/div&gt;
&lt;div align="justify"&gt;Por si ten&amp;eacute;is alguna dificultad, a parte por supuesto de poder contactar conmigo tanto dejando mensajes como en mi twitter, como en msdn o a mi email directamente, os dejo el proyecto completo para descarga, junto con los estilos y control templates que he usado. &lt;/div&gt;
&lt;div align="justify"&gt;Y recordad, con un simple comentario, pod&amp;eacute;is hacer feliz a un peque&amp;ntilde;o bloguero :)&lt;/div&gt;
&lt;div align="justify"&gt;Muchas gracias por leerme y &lt;strong&gt;Happy Coding&lt;/strong&gt;!&lt;/div&gt;
&lt;p&gt;&lt;a href="http://cid-fd100135b82f3364.office.live.com/self.aspx/.Public/ejemplos/Integracion%20Win7/WPF%20IconOverlay%20%5E0%20ProgressBar/WPF%20Icon%20Overlay%20And%20ProgressBar.zip"&gt;Descargar c&amp;oacute;digo&lt;/a&gt;&lt;/p&gt;</description></item><item><title>WPF: Obtener datos del sistema de energía de Windows 7</title><link>http://geeks.ms/wikis/wpf/wpf-obtener-datos-del-sistema-de-energ-237-a-de-windows-7/revision/0.aspx</link><pubDate>Mon, 26 Jul 2010 04:39:35 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:9</guid><dc:creator>Josué Yeray Julián Ferreiro</dc:creator><description>Revisión actual enviado a Wiki sobre WPF en Geeks•ms por Josué Yeray Julián Ferreiro a 7/26/2010 6:39:35 AM&lt;br /&gt;
&lt;p&gt;Hola a todos de nuevo! &lt;/p&gt;
&lt;div align="justify"&gt;En mi opini&amp;oacute;n uno de los grandes retos que tenemos los desarrolladores hoy en d&amp;iacute;a (entre muchos otros) es aprovechar todas las ventajas que nos ofrece el sistema operativo e intentar que nuestra aplicaci&amp;oacute;n se mimetice con el mismo de tal forma que la linea de separaci&amp;oacute;n entre aplicaci&amp;oacute;n y S.O. se desdibuje lo m&amp;aacute;ximo posible, de esa forma, nuestros usuarios tendr&amp;aacute;n menos trabajo a la hora de acostumbrarse a nuestra aplicaci&amp;oacute;n, pues la forma de usarla, y la forma en que esta se comporta les ser&amp;aacute; mucho m&amp;aacute;s familiar. &lt;!--more--&gt;En este sentido Windows 7 ha sido un gran avance, poniendo a nuestra disposici&amp;oacute;n un gran n&amp;uacute;mero de caracter&amp;iacute;sticas que podemos incorporar en nuestra aplicaci&amp;oacute;n como la gesti&amp;oacute;n de energ&amp;iacute;a, las jumplist, los Thumbnails con toolbars, las barras de progreso tras el icono de la barra de tareas y muchas otras m&amp;aacute;s. &lt;/div&gt;
&lt;div align="justify"&gt;Voy a centrar algunos art&amp;iacute;culos sobre estos temas, Windows 7 es el S.O. de m&amp;aacute;s r&amp;aacute;pida adopci&amp;oacute;n de la Historia, con 150 millones de licencias vendidas y estos n&amp;uacute;meros hacen que centrarse en incorporar caracter&amp;iacute;sticas propias de el sea una apuesta segura para nosotros y una gran ventaja tanto para nuestra aplicaci&amp;oacute;n como para nuestros usuarios. &lt;/div&gt;
&lt;div align="justify"&gt;He decidido comenzar con la gesti&amp;oacute;n de energ&amp;iacute;a, cada vez m&amp;aacute;s los port&amp;aacute;tiles ganan terreno en el &amp;aacute;mbito empresarial y en poco tiempo veremos una explosi&amp;oacute;n en tablets equipadas con Windows 7, con lo que nuestras aplicaciones se empezar&amp;aacute;n a mover a estos nuevos escenarios donde una cosa prima frente a todas: la duraci&amp;oacute;n de la bater&amp;iacute;a. &lt;/div&gt;
&lt;div align="justify"&gt;Debemos hacer que nuestras aplicaciones sean amigables con la energ&amp;iacute;a, tenemos que comprender que el escritorio y el laptop / tablet son dos escenarios distintos e intentar evitar consumir toda la vida de la bater&amp;iacute;a en un tiempo reducido, haciendo que nuestras aplicaciones conozcan el estado actual de la bater&amp;iacute;a del dispositivo sobre el que se ejecutan podremos tomar decisiones en concordancia con el % de energ&amp;iacute;a disponible e incluso sugerir a nuestro usuario que modifique la forma en que est&amp;aacute; usando nuestra aplicaci&amp;oacute;n para maximizar la vida de la misma. &lt;/div&gt;
&lt;div align="justify"&gt;Con este objetivo en mente, vamos a empezar, primero echadle un vistazo a nuestra aplicaci&amp;oacute;n terminada:&lt;/div&gt;
&lt;div align="center"&gt;&lt;a href="http://lh5.ggpht.com/_7YCdMP8inuc/TENWJfBsYxI/AAAAAAAAAE4/fuWfcoMxoRs/s1600-h/App%5B8%5D.png"&gt;&lt;img height="502" width="505" src="http://lh6.ggpht.com/_7YCdMP8inuc/TENWMLCmuaI/AAAAAAAAAE8/O2bmYHNPZaw/App_thumb%5B6%5D.png?imgmax=800" alt="App" border="0" title="App" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;Realmente es mucha informaci&amp;oacute;n con la que podemos jugar, sabemos el tipo de fuente de energ&amp;iacute;a que estamos consumiendo, si tenemos sistemas de alimentaci&amp;oacute;n ininterrumpida, la capacidad m&amp;aacute;xima y actual de la bater&amp;iacute;a, y las alertas de cargas criticas (cuando el S.O. se va a cerrar) o m&amp;iacute;nimas (cuando empieza a avisarnos) y por supuesto el % restante de la bater&amp;iacute;a. &lt;/div&gt;
&lt;div align="justify"&gt;Vamos a comenzar, lo primero es crear un nuevo proyecto WPF Application (File &amp;gt; New &amp;gt; Project), una vez creado, vamos a dise&amp;ntilde;ar la pantalla principal en el archivo MainWindow.xaml&lt;/div&gt;
&lt;div align="justify"&gt;Los estilos que he usado en esta aplicaci&amp;oacute;n est&amp;aacute;n disponibles en la descarga en el archivo Application.xaml, si ten&amp;eacute;is dudas acerca de como usar / crear estilos, echadle un vistazo en esta Wiki a los art&amp;iacute;culos sobre personalizaci&amp;oacute;n de nuestra aplicaci&amp;oacute;n.&lt;/div&gt;
&lt;div align="justify"&gt;Los controles usados son muy b&amp;aacute;sicos, la bater&amp;iacute;a que se ve en la esquina superior derecha es una progressbar, textblocks para el texto, dos checkbox, un tabcontrol y grids para ordenar todo un poco, aqu&amp;iacute; pod&amp;eacute;is ver el XAML:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Grid&amp;gt;
&amp;lt;Grid.Background&amp;gt;
&amp;lt;LinearGradientBrush StartPoint=&amp;quot;0,0&amp;quot; EndPoint=&amp;quot;1,1&amp;quot;&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;0&amp;quot; Color=&amp;quot;Black&amp;quot;&amp;gt;
&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;1&amp;quot; Color=&amp;quot;DarkGray&amp;quot;&amp;gt;
&amp;lt;/GradientStop&amp;gt;
&amp;lt;/LinearGradientBrush&amp;gt;
&amp;lt;/Grid.Background&amp;gt;
&amp;lt;Grid.RowDefinitions&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;50&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;*&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;/Grid.RowDefinitions&amp;gt;
&amp;lt;TextBlock Grid.Row=&amp;quot;0&amp;quot; Name=&amp;quot;BateriaPercent&amp;quot; FontSize=&amp;quot;24&amp;quot; 
Text=&amp;quot;Bater&amp;iacute;a restante (%):&amp;quot; VerticalAlignment=&amp;quot;Center&amp;quot; 
HorizontalAlignment=&amp;quot;Left&amp;quot; Foreground=&amp;quot;White&amp;quot; 
Margin=&amp;quot;6,0,0,0&amp;quot;/&amp;gt;
&amp;lt;ProgressBar Height=&amp;quot;40&amp;quot; Margin=&amp;quot;245,5,12,0&amp;quot; Name=&amp;quot;pBarEnergia&amp;quot; 
VerticalAlignment=&amp;quot;Top&amp;quot; Value=&amp;quot;0&amp;quot; /&amp;gt;
&amp;lt;TabControl Grid.Row=&amp;quot;1&amp;quot; Margin=&amp;quot;12,6,12,12&amp;quot; Name=&amp;quot;TabControl1&amp;quot;&amp;gt;
&amp;lt;TabItem Header=&amp;quot;Informaci&amp;oacute;n de energ&amp;iacute;a&amp;quot; Name=&amp;quot;TabItem1&amp;quot;&amp;gt;
&amp;lt;Grid&amp;gt;
&amp;lt;Grid.Background&amp;gt;
&amp;lt;ImageBrush ImageSource=&amp;quot;pack://application:,,,/WPF Power Management;component/Info.png&amp;quot; 
Stretch=&amp;quot;Uniform&amp;quot; Opacity=&amp;quot;.2&amp;quot;/&amp;gt;
&amp;lt;/Grid.Background&amp;gt;
&amp;lt;Grid.ColumnDefinitions&amp;gt;
&amp;lt;ColumnDefinition Width=&amp;quot;.4*&amp;quot;&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
&amp;lt;ColumnDefinition Width=&amp;quot;.6*&amp;quot;&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
&amp;lt;/Grid.ColumnDefinitions&amp;gt;
&amp;lt;Grid.RowDefinitions&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;.1*&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;.1*&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;.1*&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;.7*&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;/Grid.RowDefinitions&amp;gt;
&amp;lt;TextBlock Grid.Row=&amp;quot;0&amp;quot; Grid.Column=&amp;quot;0&amp;quot; Name=&amp;quot;tbFuente&amp;quot; Text=&amp;quot;Fuente de energ&amp;iacute;a:&amp;quot; 
VerticalAlignment=&amp;quot;Center&amp;quot; HorizontalAlignment=&amp;quot;Left&amp;quot; Foreground=&amp;quot;White&amp;quot; 
Margin=&amp;quot;6,0,0,0&amp;quot;/&amp;gt;
&amp;lt;TextBlock Grid.Row=&amp;quot;0&amp;quot; Grid.Column=&amp;quot;1&amp;quot; Name=&amp;quot;tbFuenteText&amp;quot; VerticalAlignment=&amp;quot;Center&amp;quot; 
HorizontalAlignment=&amp;quot;Left&amp;quot; Foreground=&amp;quot;White&amp;quot; Margin=&amp;quot;6,0,0,0&amp;quot;/&amp;gt;
&amp;lt;TextBlock Grid.Row=&amp;quot;1&amp;quot; Grid.Column=&amp;quot;0&amp;quot; Name=&amp;quot;tbBateriaPresent&amp;quot; Text=&amp;quot;Bater&amp;iacute;a presente:&amp;quot; 
VerticalAlignment=&amp;quot;Center&amp;quot; HorizontalAlignment=&amp;quot;Left&amp;quot; Foreground=&amp;quot;White&amp;quot; 
Margin=&amp;quot;6,0,0,0&amp;quot;/&amp;gt;
&amp;lt;CheckBox  Grid.Row=&amp;quot;1&amp;quot; Grid.Column=&amp;quot;1&amp;quot; Name=&amp;quot;chkBateriaPresente&amp;quot; HorizontalAlignment=&amp;quot;Left&amp;quot; 
Height=&amp;quot;20&amp;quot; VerticalAlignment=&amp;quot;Center&amp;quot;&amp;gt;&amp;lt;/CheckBox&amp;gt;
&amp;lt;TextBlock Grid.Row=&amp;quot;2&amp;quot; Grid.Column=&amp;quot;0&amp;quot; Name=&amp;quot;tbUPSPresent&amp;quot; Text=&amp;quot;UPS presente:&amp;quot; 
VerticalAlignment=&amp;quot;Center&amp;quot; HorizontalAlignment=&amp;quot;Left&amp;quot; Foreground=&amp;quot;White&amp;quot; 
Margin=&amp;quot;6,0,0,0&amp;quot;/&amp;gt;
&amp;lt;CheckBox  Grid.Row=&amp;quot;2&amp;quot; Grid.Column=&amp;quot;1&amp;quot; Name=&amp;quot;chkUpsPresente&amp;quot; HorizontalAlignment=&amp;quot;Left&amp;quot; 
Height=&amp;quot;20&amp;quot; VerticalAlignment=&amp;quot;Center&amp;quot;&amp;gt;&amp;lt;/CheckBox&amp;gt;
&amp;lt;TextBlock Grid.Row=&amp;quot;3&amp;quot; Grid.Column=&amp;quot;0&amp;quot; Name=&amp;quot;tbEstadoBateria&amp;quot; Text=&amp;quot;Estado de la bater&amp;iacute;a:&amp;quot; 
VerticalAlignment=&amp;quot;Top&amp;quot; HorizontalAlignment=&amp;quot;Left&amp;quot; Foreground=&amp;quot;White&amp;quot; Margin=&amp;quot;6,0,0,0&amp;quot;/&amp;gt;
&amp;lt;TextBlock Grid.Row=&amp;quot;3&amp;quot; Grid.Column=&amp;quot;1&amp;quot; Name=&amp;quot;tbEstado&amp;quot; VerticalAlignment=&amp;quot;Top&amp;quot; 
HorizontalAlignment=&amp;quot;Left&amp;quot; Foreground=&amp;quot;White&amp;quot;/&amp;gt;
&amp;lt;/Grid&amp;gt;
&amp;lt;/TabItem&amp;gt;
&amp;lt;/TabControl&amp;gt;
&amp;lt;/Grid&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Si lo mir&amp;aacute;is con detenimiento ver&amp;eacute;is que no es nada complicado.&lt;/div&gt;
&lt;div align="justify"&gt;Para trabajar con el sistema de energ&amp;iacute;a de Windows 7 debemos jugar con las apis de win32 (no manejadas) de windows, por ello, lo mejor es crear una nueva clase separada que se encargue de todo el trabajo de importar y llamar a las funciones necesarias del api y nos devuelva la informaci&amp;oacute;n que necesitamos.&lt;/div&gt;
&lt;div align="justify"&gt;Para esto necesitaremos los InteropServices, por lo que lo mejor es importar este namespace en esta nueva clase:&lt;/div&gt;
&lt;pre class="brush: vb;"&gt;Imports System.Runtime.InteropServices

Public Class PowerManagement
&amp;#39;...
&amp;#39;...
&amp;#39;...
End Class&lt;/pre&gt;
&lt;p&gt;Ahora debemos empezar a definir las constantes necesarias para que nuestro c&amp;oacute;digo sea m&amp;aacute;s legible en esta clase: &lt;/p&gt;
&lt;pre class="brush: vb;"&gt;&amp;#39;Esta constante identifica el valor devuelto por CallNtPowerInformation
&amp;#39;si el acceso a este m&amp;eacute;todo nos fue negado por seguridad.
Const STATUS_ACCESS_DENIED As UInteger = 3221225506

&amp;#39;Estas constantes definen el tipo de informaci&amp;oacute;n que solicitamos en el 
&amp;#39;m&amp;eacute;todo no manejado CallNtPowerInformation se usan en el par&amp;aacute;metro InformationLevel.
Const SYSTEM_POWERCAPABILITIES As Integer = 4 &amp;#39;Capacidades de energ&amp;iacute;a del sistema.
Const SYSTEM_BATTERYINFO As Integer = 5 &amp;#39;Estado de la bater&amp;iacute;a.&lt;/pre&gt;
&lt;p&gt;Como pod&amp;eacute;is ver tenemos 3 constantes, esto es lo que significa cada una: &lt;/p&gt;
&lt;table cellpadding="2" cellspacing="0" border="1" style="width:626px;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="200" valign="top" style="background-color:orange;"&gt;Constante&lt;/td&gt;
&lt;td width="426" valign="top" style="background-color:orange;"&gt;
&lt;div style="text-align:left;"&gt;Descripci&amp;oacute;n&lt;/div&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="200" valign="top"&gt;STATUS_ACCESS_DENIED&lt;/td&gt;
&lt;td width="426" valign="top"&gt;Este valor es devuelto por el m&amp;eacute;todo CallNtPowerInformation si no tenemos suficientes permisos para ejecutarlo.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="200" valign="top"&gt;SYSTEM_POWERCAPABILITIES&lt;/td&gt;
&lt;td width="426" valign="top"&gt;Este valor indica al m&amp;eacute;todo CallNtPowerInformation que deseamos obtener las capacidades de energ&amp;iacute;a del sistema.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="200" valign="top"&gt;SYSTEM_BATTERYINO&lt;/td&gt;
&lt;td width="426" valign="top"&gt;Este valor indica al m&amp;eacute;todo CallNtPowerInformation que deseamos obtener informaci&amp;oacute;n sobre la bater&amp;iacute;a del sistema.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;A continuaci&amp;oacute;n debemos definir 2 estructuras que contendr&amp;aacute;n los valores devueltos por el m&amp;eacute;todo CallNtPowerInformation. La primera se llama &lt;strong&gt;SystemPowerCapabilities&lt;/strong&gt; y contendr&amp;aacute; toda la informaci&amp;oacute;n con las capacidades de energ&amp;iacute;a del sistema: &lt;/p&gt;
&lt;pre class="brush: vb;"&gt;&amp;lt;StructLayout(LayoutKind.Sequential)&amp;gt;
Structure SystemPowerCapabilities
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public PowerButtonPresent As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public SleepButtonPresent As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public LidPresent As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public SystemS1 As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public SystemS2 As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public SystemS3 As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public SystemS4 As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public SystemS5 As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public HiberFilePresent As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public FullWake As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public VideoDimPresent As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public ApmPresent As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public UpsPresent As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public ThermalControl As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public ProcessorThrottle As Boolean
Public ProcessorMinThrottle As Byte
Public ProcessorMaxThrottle As Byte
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public FastSystemS4 As Boolean
Public spare2_1 As Byte
Public spare2_2 As Byte
Public spare2_3 As Byte
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public DiskSpinDown As Boolean
Public spare3_1 As Byte
Public spare3_2 As Byte
Public spare3_3 As Byte
Public spare3_4 As Byte
Public spare3_5 As Byte
Public spare3_6 As Byte
Public spare3_7 As Byte
Public spare3_8 As Byte
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public SystemBatteriesPresent As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public BatteriesAreShortTerm As Boolean
Public granularity As Integer
Public capacity As Integer
End Structure&lt;/pre&gt;
&lt;div align="justify"&gt;Como pod&amp;eacute;is observar hay mucha m&amp;aacute;s informaci&amp;oacute;n que la que yo he escogido para mostrar, realmente podemos controlar de una forma milim&amp;eacute;trica el consumo energ&amp;eacute;tico y las capacidades t&amp;eacute;cnicas en cuanto a energ&amp;iacute;a de la m&amp;aacute;quina en la que nos encontramos.&lt;/div&gt;
&lt;div align="justify"&gt;El decorador de la estructura &lt;span style="color:maroon;"&gt;&lt;strong&gt;&amp;lt;StructureLaout(LayoutKind.Sequential)&amp;gt;&lt;/strong&gt;&lt;/span&gt; ind&amp;iacute;ca al interop que los campos de la misma se ordenar&amp;aacute;n de forma consecutiva tal y como los hemos expresado aqu&amp;iacute;. El decorador &lt;span style="color:maroon;"&gt;&lt;strong&gt;&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;&lt;/strong&gt;&lt;/span&gt; le indica al interop de que forma debe trabajar con el tipo de dato a continuaci&amp;oacute;n (boolean en todos los casos) para facilitar la conversi&amp;oacute;n de informaci&amp;oacute;n entre tipos de datos .NET (manejados) y Win32 (no manejados).&lt;/div&gt;
&lt;p&gt;La segunda estructura es &lt;strong&gt;SystemBatteryState&lt;/strong&gt; y contendr&amp;aacute; toda la informaci&amp;oacute;n referente a la bater&amp;iacute;a de nuestro equipo: &lt;/p&gt;
&lt;pre class="brush: vb;"&gt;&amp;lt;StructLayout(LayoutKind.Sequential)&amp;gt;
Structure SystemBatteryState
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public AcOnLine As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public BatteryPresent As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public Charging As Boolean
&amp;lt;MarshalAs(UnmanagedType.I1)&amp;gt;
Public Discharging As Boolean
Public spare1 As Byte
Public spare2 As Byte
Public spare3 As Byte
Public spare4 As Byte
Public MaxCapacity As UInteger
Public RemainingCapacity As UInteger
Public Rate As UInteger
Public EstimatedTime As UInteger
Public DefaultAlert1 As UInteger
Public DefaultAlert2 As UInteger
End Structure&lt;/pre&gt;
&lt;div align="justify"&gt;Esta es bastante m&amp;aacute;s peque&amp;ntilde;a que la anterior y usa los mismos tipos de decorados.&lt;/div&gt;
&lt;div align="justify"&gt;Para terminar de declarar el acceso a Win32 solo nos falta importar la funci&amp;oacute;n necesaria desde la Dll de win32 encargada de las tareas de gesti&amp;oacute;n de energ&amp;iacute;a &lt;strong&gt;powrprof.dll&lt;/strong&gt;:&lt;/div&gt;
&lt;pre class="brush: vb;"&gt;&amp;lt;DllImport(&amp;quot;powrprof.dll&amp;quot;, SetLastError:=True)&amp;gt;
Private Shared Function CallNtPowerInformation(ByVal InformationLevel As Int32, 
ByVal lpInputBuffer As IntPtr, 
ByVal nInputBufferSize As UInt32,
ByVal lpOutputBuffer As IntPtr, 
ByVal nOutputBufferSize As UInt32) As UInt32
End Function&lt;/pre&gt;
&lt;div align="justify"&gt;Esta funci&amp;oacute;n CallNtPowerInformation ser&amp;aacute; la que usaremos para comunicarnos con Windows 7 y obtener todos los datos de energ&amp;iacute;a que necesitemos. Tiene 5 par&amp;aacute;metros, el 2&amp;ordm; y 3&amp;ordm; par&amp;aacute;metro no son importantes, puesto que no queremos enviarle informaci&amp;oacute;n, tan solo recibir, el 2&amp;ordm; se env&amp;iacute;a con Nothing y el 3&amp;ordm; se env&amp;iacute;a 0, en cuanto al primer par&amp;aacute;metro, aqu&amp;iacute; es donde usaremos las dos constantes definidas m&amp;aacute;s arriba (SYSTEM_) para indicarle a la funci&amp;oacute;n que tipo de informaci&amp;oacute;n estamos solicitando, el 4&amp;ordm; par&amp;aacute;metro es un puntero a la variable en la que queramos almacenar la informaci&amp;oacute;n recibida y el 5&amp;ordm; es el tama&amp;ntilde;o actual de esa variable.&lt;/div&gt;
&lt;div align="justify"&gt;Bien, ahora que hemos terminado de declarar todo lo necesario para trabajar con el api de win32, vamos a crear dos nuevos m&amp;eacute;todos en esta clase que se encarguen de obtener la informaci&amp;oacute;n que deseamos.&lt;/div&gt;
&lt;div align="justify"&gt;En primer lugar creamos el m&amp;eacute;todo &lt;strong&gt;GetPowerCapabilities&lt;/strong&gt; con este c&amp;oacute;digo:&lt;/div&gt;
&lt;pre class="brush: vb;"&gt;Public Shared Function GetPowerCapabilities() As SystemPowerCapabilities
Dim PowerCapabilities As SystemPowerCapabilities
Dim Status As IntPtr = IntPtr.Zero
Dim ReturnValue As UInteger
Try
Status = Marshal.AllocCoTaskMem(Marshal.SizeOf(GetType(SystemPowerCapabilities)))
ReturnValue = CallNtPowerInformation(SYSTEM_POWERCAPABILITIES, Nothing, 0, Status, 
Marshal.SizeOf(GetType(SystemPowerCapabilities)))
If ReturnValue = STATUS_ACCESS_DENIED Then
MessageBox.Show(&amp;quot;Su usuario no tiene permisos de acceso suficientes para obtener 
informaci&amp;oacute;n sobre el sistema de energ&amp;iacute;a.&amp;quot;)
Return Nothing
End If
PowerCapabilities = Marshal.PtrToStructure(Status, GetType(SystemPowerCapabilities))
Catch ex As Exception
Finally
Marshal.FreeCoTaskMem(Status)
End Try
Return PowerCapabilities
End Function&lt;/pre&gt;
&lt;div align="justify"&gt;Vamos a revisar con detenimiento el c&amp;oacute;digo de este m&amp;eacute;todo, si no has trabajado antes con funciones del win32 desde .NET ver&amp;aacute;s un par de cosas que te sonar&amp;aacute;n a chino, sobre todo las que empiezan por Marshal.&lt;/div&gt;
&lt;div align="justify"&gt;Marshal es una clase del namespace InteropServices que nos facilita el trabajo con m&amp;eacute;todos no manejados, es muy completa y tiene muchos m&amp;eacute;todos, en nuestro caso usamos 4:&lt;/div&gt;
&lt;table cellpadding="2" cellspacing="0" border="1" style="width:626px;"&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td width="200" valign="top" style="background-color:orange;"&gt;
&lt;div align="justify"&gt;M&amp;eacute;todo&lt;/div&gt;
&lt;/td&gt;
&lt;td width="426" valign="top" style="background-color:orange;"&gt;Descripci&amp;oacute;n&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="200" valign="top"&gt;
&lt;div align="justify"&gt;Marshal.AllocCoTaskMem&lt;/div&gt;
&lt;/td&gt;
&lt;td width="426" valign="top"&gt;Nos sirve para reservar un bloque de memoria del asignador de tareas COM del tama&amp;ntilde;o indicado y nos devuelve un puntero al bloque asignado.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="200" valign="top"&gt;Marshal.FreeCoTaskMem&lt;/td&gt;
&lt;td width="426" valign="top"&gt;Con este m&amp;eacute;todo liberamos un bloque de memoria obtenido con anterioridad con el m&amp;eacute;todo AllocCoTaskMem.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="200" valign="top"&gt;Marshal.PtrToStructure&lt;/td&gt;
&lt;td width="426" valign="top"&gt;Copiamos el contenido del bloque de memoria al que apunta el puntero que le indicamos a una estructura para poder acceder a los datos.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td width="200" valign="top"&gt;Marshal.SizeOf&lt;/td&gt;
&lt;td width="426" valign="top"&gt;Devuelve el tama&amp;ntilde;o en Bytes de un objeto, sin tener en cuenta la sobrecarga de los tipos manejados, nos devuelve el tama&amp;ntilde;o no manejado, que es el necesario para las funciones no manejadas.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;div align="justify"&gt;En esta funci&amp;oacute;n usamos la tercera constante que hab&amp;iacute;amos declarado (STATUS_ACCESS_DENIED) si el resultado de la llamada a CallNtPowerInformation devuelve este valor, significa que nuestro usuario no tiene permisos para realizar esta llamada.&lt;/div&gt;
&lt;div align="justify"&gt;En &amp;uacute;ltimo lugar, debemos crear el segundo m&amp;eacute;todo que interactuar&amp;aacute; con el API de win32, &lt;strong&gt;GetBatteryInformation&lt;/strong&gt;:&lt;/div&gt;
&lt;pre class="brush: vb;"&gt;Public Shared Function GetBatteryInformation() As SystemBatteryState
Dim Status As IntPtr = IntPtr.Zero
Dim BattStatus As SystemBatteryState
Dim ReturnValue As UInteger
Try
Status = Marshal.AllocCoTaskMem(Marshal.SizeOf(GetType(SystemBatteryState)))
ReturnValue = CallNtPowerInformation(SYSTEM_BATTERYINFO, Nothing, 0, Status, 
Marshal.SizeOf(GetType(SystemBatteryState)))
If ReturnValue = STATUS_ACCESS_DENIED Then
MessageBox.Show(&amp;quot;Su usuario no tiene permisos de acceso suficientes para obtener 
informaci&amp;oacute;n sobre el estado de la bater&amp;iacute;a.&amp;quot;)
Return Nothing
End If
BattStatus = Marshal.PtrToStructure(Status, GetType(SystemBatteryState))
Catch ex As Exception
Finally
Marshal.FreeCoTaskMem(Status)
End Try
Return BattStatus
End Function&lt;/pre&gt;
&lt;div align="justify"&gt;El c&amp;oacute;digo es b&amp;aacute;sicamente el mismo, si te fijas bien los &amp;uacute;nicos cambios son el primer par&amp;aacute;metro de la funci&amp;oacute;n CallNtPowerInformation y el tipo de estructura que queremos obtener, en este caso lo que obtenemos es todos los detalles sobre la bater&amp;iacute;a del sistema, carga m&amp;aacute;xima, carga actual, fuente de energ&amp;iacute;a, etc&amp;hellip;&lt;/div&gt;
&lt;p&gt;Bueno, con esto hemos terminado el trabajo con el API de Win32, ahora solo nos queda algo m&amp;aacute;s de c&amp;oacute;digo en nuestra ventana principal de WPF para poder hacer que todo esto funcione. Empecemos con las declaraciones de variables, necesitamos 3 variables globales de la clase y privadas: &lt;/p&gt;
&lt;pre class="brush: vb;"&gt;Private MySPC As PowerManagement.SystemPowerCapabilities
Private MyBatt As PowerManagement.SystemBatteryState
Private WithEvents Tmr As New DispatcherTimer&lt;/pre&gt;
&lt;p&gt;B&amp;aacute;sicamente, definimos una variable por cada estructura necesaria, SystemPowerCapabilities y SystemBatteryState y un control DispatcherTimer que ser&amp;aacute; el encargado de refrescar constantemente la informaci&amp;oacute;n del sistema de energ&amp;iacute;a. En el evento Load, configuraremos el Timer y comprobaremos la versi&amp;oacute;n de sistema operativo sobre la cual nos estamos ejecutando, ten en cuenta que este c&amp;oacute;digo es para Windows 7 y lo m&amp;aacute;s probable es que falle en algunos puntos en XP o Vista: &lt;/p&gt;
&lt;pre class="brush: vb;"&gt;&amp;#39;Comprobamos que estemos en un Windows 7:
If Environment.OSVersion.Version.Major = 6 And 
Environment.OSVersion.Version.Minor &amp;gt; 0 Then
Tmr.Interval = New TimeSpan(0, 0, 1)
Tmr.IsEnabled = True
Else
MessageBox.Show(&amp;quot;Es necesario windows 7 
para poder ejecutar este programa.&amp;quot;)
End If&lt;/pre&gt;
&lt;div align="justify"&gt;Este es un c&amp;oacute;digo muy sencillo, sobre todo despu&amp;eacute;s del empacho de Interop y Win32 que nos hemos dado anteriormente jeje, simplemente comprobamos que estemos ejecutando Windows 7, que a pesar de su nombre es la versi&amp;oacute;n 6.1 del sistema operativo, por lo que comprobamos que estemos en un sistema superior al 6.0, es muy posible que el pr&amp;oacute;ximo windows soporte este c&amp;oacute;digo, as&amp;iacute; que lo mejor es buscar un sistema cuya versi&amp;oacute;n sea superior a 6.0 (Windows Vista). Una vez hecho esto configuramos el intervalo del timer a 1 segundo y lo habilitamos.&lt;/div&gt;
&lt;div align="justify"&gt;El control DispatcherTimer no dispara el evento Elapsed como el Timer de siempre de Windows Forms, en este caso debemos manejar el evento Tick:&lt;/div&gt;
&lt;pre class="brush: vb;"&gt;Private Sub Tmr_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles Tmr.Tick
Tmr.IsEnabled = False
MySPC = PowerManagement.GetPowerCapabilities()
&amp;#39;Comprobamos si existe bater&amp;iacute;a en el equipo:
If MySPC.SystemBatteriesPresent = True Then
SetValues()
End If
Tmr.IsEnabled = True
End Sub&lt;/pre&gt;
&lt;div align="justify"&gt;En este caso cuando recibimos el evento lo primero que hacemos es desactivar el timer, ya que no queremos que se dispare de nuevo hasta que hayamos terminado, llamamos a nuestro m&amp;eacute;todo GetPowerCapabilities y comprobamos si el equipo contiene bater&amp;iacute;as, si es as&amp;iacute; llamamos a un m&amp;eacute;todo SetValues que se encarga de pasar los valores obtenidos a nuestros controles de visualizaci&amp;oacute;n y por &amp;uacute;ltimo volvemos a habilitar el timer para que siga su ciclo de refresco normal.&lt;/div&gt;
&lt;div align="justify"&gt;El &amp;uacute;ltimo m&amp;eacute;todo que necesitamos se llama SetValues, simplemente obtiene los valores de energ&amp;iacute;a necesarios y los pasa a los controles para que los visualicemos:&lt;/div&gt;
&lt;pre class="brush: vb;"&gt;Private Sub SetValues()
tbFuenteText.Text = If(MyBatt.AcOnLine = True, &amp;quot;Corriente Alterna&amp;quot;, &amp;quot;Bater&amp;iacute;a&amp;quot;)
chkBateriaPresente.IsChecked = MySPC.SystemBatteriesPresent
chkUpsPresente.IsChecked = MySPC.UpsPresent
&amp;#39;Obtenemos informaci&amp;oacute;n de la bater&amp;iacute;a
MyBatt = PowerManagement.GetBatteryInformation()
pBarEnergia.Value = Math.Round((MyBatt.RemainingCapacity * 100) / MyBatt.MaxCapacity, 0)
tbEstado.Text = &amp;quot;Corriente externa: &amp;quot;+If(MyBatt.AcOnLine=True,&amp;quot;SI&amp;quot;,&amp;quot;NO&amp;quot;)+vbCrLf+ 
&amp;quot;Capacidad M&amp;aacute;xima: &amp;quot;+MyBatt.MaxCapacity.ToString+&amp;quot;mWh&amp;quot;+vbCrLf+
&amp;quot;Capacidad Actual: &amp;quot;+MyBatt.RemainingCapacity.ToString+&amp;quot;mWh&amp;quot;+vbCrLf+
&amp;quot;Alerta carga minima: &amp;quot;+MyBatt.DefaultAlert2.ToString+&amp;quot;mWh&amp;quot;+vbCrLf+
&amp;quot;Alerta carga cr&amp;iacute;tica: &amp;quot;+MyBatt.DefaultAlert1.ToString+&amp;quot;mWh&amp;quot;
End Sub&lt;/pre&gt;
&lt;div align="justify"&gt;Y con esto, si compilamos nuestra aplicaci&amp;oacute;n (y estamos trabajando en Windows 7, con un portatil o tablet) deber&amp;iacute;amos ver toda la informaci&amp;oacute;n de energ&amp;iacute;a que os indique al principio del art&amp;iacute;culo.&lt;/div&gt;
&lt;div align="justify"&gt;Por si ten&amp;eacute;is alguna dificultad, a parte por supuesto de poder contactar conmigo tanto dejando mensajes como en mi twitter, como en msdn o a mi email directamente, os dejo el proyecto completo para descarga, junto con los estilos y control templates que he usado. &lt;/div&gt;
&lt;div align="justify"&gt;Y recordad, con un simple comentario, pod&amp;eacute;is hacer feliz a un peque&amp;ntilde;o bloguero :)&lt;/div&gt;
&lt;div align="justify"&gt;Muchas gracias por leerme y &lt;strong&gt;Happy Coding&lt;/strong&gt;!&lt;/div&gt;
&lt;p&gt;&lt;a href="http://cid-fd100135b82f3364.office.live.com/self.aspx/.Public/ejemplos/Integracion%20Win7/WPF%20Power%20Management/WPF%20Power%20Management.zip"&gt;Descargar c&amp;oacute;digo&lt;/a&gt;&lt;/p&gt;</description></item><item><title>WPF: Personalizar nuestra aplicación con Styles y Control Templates (II)</title><link>http://geeks.ms/wikis/wpf/wpf-personalizar-nuestra-aplicaci-243-n-con-styles-y-control-templates-ii/revision/0.aspx</link><pubDate>Mon, 26 Jul 2010 04:35:54 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:8</guid><dc:creator>Josué Yeray Julián Ferreiro</dc:creator><description>Revisión actual enviado a Wiki sobre WPF en Geeks•ms por Josué Yeray Julián Ferreiro a 7/26/2010 6:35:54 AM&lt;br /&gt;
&lt;h2&gt;WPF: Personalizar nuestra aplicaci&amp;#243;n con Styles y Control Templates (II)&lt;/h2&gt;
&lt;div style="font-size: 90%;"&gt;Archivado en: &lt;span style="text-decoration: line-through; color: red;"&gt;WPF&lt;/span&gt;&lt;span style="text-decoration: line-through; color: red;"&gt;,&lt;/span&gt; &lt;span style="text-decoration: line-through; color: red;"&gt;Styles&lt;/span&gt;&lt;span style="text-decoration: line-through; color: red;"&gt;,&lt;/span&gt; &lt;span style="text-decoration: line-through; color: red;"&gt;ControlTemplate&lt;/span&gt;&lt;/div&gt;

&lt;div align="justify"&gt;En la primera parte de este art&amp;iacute;culo aprendimos las distintas formas que nos ofrece WPF para personalizar nuestros controles, centr&amp;aacute;ndonos en los estilos y las plantillas de control. Le dimos un repaso a la teor&amp;iacute;a b&amp;aacute;sica sobre elementos comunes y diccionarios de recursos.&lt;/div&gt;
&lt;div align="justify"&gt;&lt;/div&gt;
&lt;!--more--&gt;
&lt;div align="justify"&gt;&lt;/div&gt;
&lt;div align="justify"&gt;&lt;/div&gt;
&lt;div align="justify"&gt;Si te lo perdiste o quieres darle un repaso aqu&amp;iacute; lo tienes:&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;WPF&lt;a href="/wikis/wpf/wpf-personalizar-nuestra-aplicaci-243-n-con-styles-y-control-templates-i.aspx"&gt;: Personalizar nuestra aplicaci&amp;oacute;n con Styles y Control Templates (I) &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div align="justify"&gt;Esta vez vamos a ir directamente al meollo de la cuesti&amp;oacute;n, examinando a fondo como personalizar varios controles est&amp;aacute;ndar de WPF como son los siguientes:&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Button &lt;/li&gt;
&lt;li&gt;Textbox &lt;/li&gt;
&lt;li&gt;Scrollbars (Horizontales y Verticales) &lt;/li&gt;
&lt;li&gt;ProgressBar &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Button&lt;/h3&gt;
&lt;div align="justify"&gt;El bot&amp;oacute;n es uno de los controles m&amp;aacute;s sencillos de personalizar, pero a su vez es uno de los controles m&amp;aacute;s &amp;uacute;tiles y el usuario interact&amp;uacute;a mucho con ellos, por lo que es importante hacerlos lo m&amp;aacute;s atractivos que podamos:&lt;/div&gt;
&lt;div align="center"&gt;&lt;a href="http://lh5.ggpht.com/_7YCdMP8inuc/TApTZLASV6I/AAAAAAAAADo/N5o_BEHPahA/s1600-h/botones7.png"&gt;&lt;img height="203" width="153" src="http://lh5.ggpht.com/_7YCdMP8inuc/TApTZlikVRI/AAAAAAAAADs/IZDIl_X6BHU/botones_thumb5.png?imgmax=800" alt="botones" border="0" title="botones" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;Algo muy importante a recordar cuando creamos nuestras propias plantillas es que estas substituyen completamente la plantilla por defecto del control, por lo que si queremos dar indicaciones visuales de que nuestro bot&amp;oacute;n est&amp;aacute; activado, desactivado, pulsado, con foco o con el rat&amp;oacute;n sobre el, deberemos hacerlo nosotros, esto lo lograremos aprovech&amp;aacute;ndonos de los Triggers del control.&lt;/div&gt;
&lt;div align="justify"&gt;Lo primero que vamos a hacer es definir un estilo nuevo para todos los controles del tipo Button, pues no queremos aplicarlo de forma selectiva a ciertos botones, queremos que sea la apariencia predeterminada de cualquier bot&amp;oacute;n en nuestra aplicaci&amp;oacute;n:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Style TargetType=&amp;quot;{x:Type Button}&amp;quot;&amp;gt;

&amp;lt;/Style&amp;gt;&lt;/pre&gt;
&lt;p&gt;Simplemente en la cabecera Style definimos la propiedad TargetType al tipo Button. Ahora vamos a incluir algunas propiedades por defecto para nuestro bot&amp;oacute;n dentro de este bloque Style: &lt;/p&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Setter Property=&amp;quot;OverridesDefaultStyle&amp;quot; Value=&amp;quot;True&amp;quot; /&amp;gt;
&amp;lt;Setter Property=&amp;quot;SnapsToDevicePixels&amp;quot; Value=&amp;quot;True&amp;quot; /&amp;gt;
&amp;lt;Setter Property=&amp;quot;Foreground&amp;quot; Value=&amp;quot;White&amp;quot; /&amp;gt; &lt;/pre&gt;
&lt;div align="justify"&gt;El objeto Setter es muy sencillo, simplemente tiene el atributo Property que especifica el nombre de la propiedad que queremos establecer y el atributo Value que especifica el valor a aplicar en esa propiedad. La propiedad &lt;strong&gt;OverridesDefaultStyle&lt;/strong&gt; indica a nuestro control que nunca se usar&amp;aacute; el tema por defecto del control para ninguna propiedad, aunque esta no est&amp;eacute; definida en nuestro estilo o plantilla, si no hemos implementado algo, es porque no lo necesitamos o lo suplimos de alguna otra forma. &lt;strong&gt;SnapsToDevicePixels&lt;/strong&gt; indica a nuestro estilo que el dibujado de nuestro control debe usar pixeles dependientes del dispositivo. Por defecto WPF usa el DPI actual para obtener independencia de la resoluci&amp;oacute;n a la hora de dibujar, pero esto puede causar un efecto difuso o borroso, y en nuestro caso queremos que nuestros preciosos controles se vean bien, por lo que indicando esta propiedad evitaremos este dibujado difuso o borroso. &lt;strong&gt;Foreground&lt;/strong&gt;, bueno no hay mucho que decir, en el caso de nuestro bot&amp;oacute;n la propiedad Foreground afecta al texto del mismo. Puesto que nuestro bot&amp;oacute;n es oscuro y por defecto el texto es de color negro, ser&amp;iacute;a un incordio estar recorriendo todos los botones cambiando el texto a Blanco u otro color y precisamente queremos que modificar el aspecto de nuestra aplicaci&amp;oacute;n se haga de forma centralizada, por lo que al incluir esta propiedad todos los botones obtendr&amp;aacute;n texto blanco.&lt;/div&gt;
&lt;div align="justify"&gt;El &amp;uacute;ltimo objeto Setter que necesitamos establecer&amp;aacute; la propiedad Template del bot&amp;oacute;n y dentro de este Setter definiremos nuestro Control Template:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Setter Property=&amp;quot;Template&amp;quot;&amp;gt;
&amp;lt;Setter.Value&amp;gt;
&amp;lt;ControlTemplate x:Name=&amp;quot;tmpltButton&amp;quot;&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;
&amp;lt;/Setter.Value&amp;gt;
&amp;lt;/Setter&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;A diferencia del estilo, que establecia su propiedad TargetType, en el ControlTemplate establecemos x:Name pues esta contenido dentro del estilo y se aplicar&amp;aacute; autom&amp;aacute;ticamente all&amp;iacute; donde se aplique el estilo.&lt;/div&gt;
&lt;div align="justify"&gt;Dentro del objeto ControlTemplate podemos empezar a definir nuestro bot&amp;oacute;n, aqu&amp;iacute; es donde WPF te golpea con un derroche de realidad: ControlTemplate es una pizarra en blanco en la que puedes pintar TODO lo que tu quieras y el resultado final, ser&amp;aacute; el aspecto de tu bot&amp;oacute;n, no hay reglas (o no demasiadas), solo creatividad.&lt;/div&gt;
&lt;div align="justify"&gt;Nuestro bot&amp;oacute;n se va a componer de 6 controles b&amp;aacute;sicos: 1 Grid para mantener todo unido, 4 Borders para crear la forma y relleno y 1 ContentPresenter que presentar&amp;aacute; el contenido del bot&amp;oacute;n, quedar&amp;iacute;a algo as&amp;iacute;:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Grid&amp;gt;
&amp;lt;Border x:Name=&amp;quot;BaseRectangle&amp;quot; 
Background=&amp;quot;{StaticResource BaseColor}&amp;quot; 
CornerRadius=&amp;quot;10,0,10,0&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;GlassRectangle&amp;quot; 
Background=&amp;quot;{StaticResource GlassFX}&amp;quot; 
CornerRadius=&amp;quot;10,0,10,0&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;GlowRectangle&amp;quot; 
Background=&amp;quot;{StaticResource GlowFX}&amp;quot; 
CornerRadius=&amp;quot;10,0,10,0&amp;quot; 
Opacity=&amp;quot;0&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;ButtonBorder&amp;quot; 
CornerRadius=&amp;quot;10,0,10,0&amp;quot; 
BorderBrush=&amp;quot;Black&amp;quot; 
Opacity=&amp;quot;1&amp;quot;  
BorderThickness=&amp;quot;1&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;ContentPresenter x:Name=&amp;quot;ButtonContent&amp;quot; 
Opacity=&amp;quot;.7&amp;quot; 
Content=&amp;quot;{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}&amp;quot; 
HorizontalAlignment=&amp;quot;center&amp;quot; 
VerticalAlignment=&amp;quot;center&amp;quot;&amp;gt;
&amp;lt;/ContentPresenter&amp;gt;
&amp;lt;/Grid&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Simplemente tenemos un grid que contiene nuestros controles Border y el ContentPresenter, el primer Border BaseRectangle es nuestra capa base de pintura, como veis todos los colores se definen con enlace a recursos que ya establecimos en nuestro diccionario de recursos, de esta forma si cambiamos el color BaseColor, cambiar&amp;aacute; en todos los sitios donde est&amp;eacute; aplicado. Todos los Border comparten el mismo valor de CornerRadius para que el control tenga la apariencia deseada, los 4 valores de CornerRadius siguen el orden de las agujas del reloj: &lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div align="justify"&gt;Esquina Superior Derecha&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;Esquina Superior Izquierda&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;Esquina Inferior Izquierda&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;Esquina Inferior Derecha&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div align="justify"&gt;Aplicando un valor de 10 en las esquinas superior derecha e inferior izquierda y un valor de 0 en las otras conseguimos el efecto deseado.&lt;/div&gt;
&lt;div align="justify"&gt;La propiedad Background de los dos primeros Border define la apariencia general de nuestro bot&amp;oacute;n, el primero aplicando un color base (nuestro recurso BaseColor) y el segundo aplicando un degradado llamado GlassFX que es el encargado de darle a nuestro bot&amp;oacute;n el efecto de reflejo de cristal.&lt;/div&gt;
&lt;div align="justify"&gt;El tercer Border define en el background el recurso GlowFX y es el usado para la animaci&amp;oacute;n del foco del bot&amp;oacute;n, por defecto establecemos su Opacity a 0, para animar esta propiedad m&amp;aacute;s adelante con los Event Triggers de nuestra plantilla.&lt;/div&gt;
&lt;div align="justify"&gt;El &amp;uacute;ltimo Border define el borde externo del bot&amp;oacute;n, en este caso no definimos la propiedad Background por lo que es transparente pero definimos la propiedad BorderBrush que establece el color del borde y BorderThickness que establece el grosor del borde.&lt;/div&gt;
&lt;div align="justify"&gt;La apariencia de nuestro bot&amp;oacute;n ya est&amp;aacute; casi completa, solo necesitamos mostrar el contenido que tenga cada bot&amp;oacute;n, ya sea texto, im&amp;aacute;genes o cualquier combinaci&amp;oacute;n de ambos, para esto usamos el control ContentPresenter. La propiedad m&amp;aacute;s interesante en el es Content, la enlazamos directamente al Content establecido en nuestro bot&amp;oacute;n:&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div align="justify"&gt;Binding Path= Indica la propiedad a la que queremos enlazarnos.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;RelativeSource= Indica la fuente de esta propiedad, en nuestro caso la dirigimos a una fuente relativa de tipo templatedparent, es decir el objeto padre de nuestra plantilla, que en este caso ser&amp;aacute; cada bot&amp;oacute;n que la use.&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div align="justify"&gt;Con esto ya est&amp;aacute; totalmente terminada la apariencia de nuestro bot&amp;oacute;n. si colocamos un bot&amp;oacute;n en una ventana de pruebas veremos que usa nuestro estilo autom&amp;aacute;ticamente. Al ejecutar, no obstante, notaremos que el bot&amp;oacute;n no reacciona de ninguna manera al pasar el rat&amp;oacute;n sobre el o hacer click lo cual es muy poco intuitivo para el usuario final, esto lo resolveremos usando los Triggers del Controltemplate, justo despu&amp;eacute;s de la Grid, a&amp;ntilde;adimos un objeto ControlTemplate.Triggers:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate.Triggers&amp;gt;
&amp;lt;EventTrigger RoutedEvent=&amp;quot;Button.MouseLeave&amp;quot;&amp;gt;
&amp;lt;EventTrigger.Actions&amp;gt;
&amp;lt;BeginStoryboard Storyboard=&amp;quot;{StaticResource GlowOut}&amp;quot;&amp;gt;
&amp;lt;/BeginStoryboard&amp;gt;
&amp;lt;/EventTrigger.Actions&amp;gt;
&amp;lt;/EventTrigger&amp;gt;
&amp;lt;EventTrigger RoutedEvent=&amp;quot;Button.MouseEnter&amp;quot;&amp;gt;
&amp;lt;EventTrigger.Actions&amp;gt;
&amp;lt;BeginStoryboard Storyboard=&amp;quot;{StaticResource GlowIn}&amp;quot;&amp;gt;
&amp;lt;/BeginStoryboard&amp;gt;
&amp;lt;/EventTrigger.Actions&amp;gt;
&amp;lt;/EventTrigger&amp;gt;
&amp;lt;EventTrigger RoutedEvent=&amp;quot;Button.LostFocus&amp;quot;&amp;gt;
&amp;lt;EventTrigger.Actions&amp;gt;
&amp;lt;BeginStoryboard Storyboard=&amp;quot;{StaticResource GlowOut}&amp;quot;&amp;gt;
&amp;lt;/BeginStoryboard&amp;gt;
&amp;lt;/EventTrigger.Actions&amp;gt;
&amp;lt;/EventTrigger&amp;gt;
&amp;lt;EventTrigger RoutedEvent=&amp;quot;Button.GotFocus&amp;quot;&amp;gt;
&amp;lt;EventTrigger.Actions&amp;gt;
&amp;lt;BeginStoryboard Storyboard=&amp;quot;{StaticResource GlowIn}&amp;quot;&amp;gt;
&amp;lt;/BeginStoryboard&amp;gt;
&amp;lt;/EventTrigger.Actions&amp;gt;
&amp;lt;/EventTrigger&amp;gt;
&amp;lt;Trigger Property=&amp;quot;Button.IsPressed&amp;quot; Value=&amp;quot;True&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Background&amp;quot; TargetName=&amp;quot;GlowRectangle&amp;quot;
Value=&amp;quot;{StaticResource GlowFXPressed}&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Opacity&amp;quot; TargetName=&amp;quot;ButtonContent&amp;quot; 
Value=&amp;quot;1&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;/Trigger&amp;gt;
&amp;lt;Trigger Property=&amp;quot;IsEnabled&amp;quot; Value=&amp;quot;False&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Opacity&amp;quot; TargetName=&amp;quot;ButtonContent&amp;quot; 
Value=&amp;quot;.3&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Opacity&amp;quot; TargetName=&amp;quot;ButtonBorder&amp;quot; 
Value=&amp;quot;.5&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Background&amp;quot; TargetName=&amp;quot;GlassRectangle&amp;quot; 
Value=&amp;quot;{StaticResource GlassFXDisabled}&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;/Trigger&amp;gt;
&amp;lt;/ControlTemplate.Triggers&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Como pod&amp;eacute;is ver en este snippet, tenemos dos tipos de Triggers: Trigger y EventTrigger.&lt;/div&gt;
&lt;div align="justify"&gt;Los Trigger se disparan cuando la propiedad Indicada tiene el valor indicado, mientras que los EventTrigger se disparan cuando el evento indicado es lanzado. La mayor diferencia es que los EventTriggers nos permiten lanzar animaciones como indicaci&amp;oacute;n visual a un cambio en el estado del control. &lt;/div&gt;
&lt;div align="justify"&gt;En el caso de nuestro Bot&amp;oacute;n respondemos a 4 eventos: MouseEnter, MouseLeave, LostFocus y GotFocus. &lt;/div&gt;
&lt;div align="justify"&gt;Cada EventTrigger define un objeto EventTrigger.Actions y dentro de este encontramos el objeto BeginStoryboard, que inicia la animaci&amp;oacute;n indicada en su propiedad Storyboard (En el primer cap&amp;iacute;tulo ya hablamos sobre las animaciones y explicamos como crear animaciones sencillas).&lt;/div&gt;
&lt;div align="justify"&gt;Tambi&amp;eacute;n controlamos el cambio de 2 propiedades: IsPressed e IsEnabled.&lt;/div&gt;
&lt;div align="justify"&gt;Cada uno de estos 2 triggers se lanzar&amp;aacute; cuando la propiedad indicada tenga el valor indicado (Cuando IsPressed sea True y cuando IsEnabled sea false) y aplicar&amp;aacute; por medio de los objetos Setter valores a otras propiedades. Cada objeto Setter define Property que indica el nombre de la propiedad a modificar, TargetName que indica el nombre del objeto de nuestra plantilla al que afectar&amp;aacute; la modificaci&amp;oacute;n y value que indica el nuevo valor que tendr&amp;aacute; la propiedad.&lt;/div&gt;
&lt;div align="justify"&gt;Si volvemos a ejecutar nuestro proyecto comprobaremos que ahora gracias a los Triggers, nuestro bot&amp;oacute;n reacciona al pasar el rat&amp;oacute;n sobre el, al abandonarlo el rat&amp;oacute;n, al llegar a el con el tabulador o al salir de el, al presionarlo y al desactivarlo,con lo que conseguimos una respuesta visual muy importante para nuestro usuario final.&lt;/div&gt;
&lt;h3&gt;Textbox&lt;/h3&gt;
&lt;div align="justify"&gt;En general nuestro control Textbox se compone de forma muy parecida al Bot&amp;oacute;n, el mayor cambio en la composici&amp;oacute;n del control viene dado porque en este caso, en vez de usar un control ContentPresenter usaremos un control ScrollViewer, (que personalizaremos m&amp;aacute;s adelante tambi&amp;eacute;n) para permitir que el usuario pueda usar las barras de desplazamiento vertical y horizontal en una caja de texto multilinea:&lt;/div&gt;
&lt;div align="center"&gt;&lt;a href="http://lh4.ggpht.com/_7YCdMP8inuc/TApTaTg4k8I/AAAAAAAAADw/DQDg751WvAA/s1600-h/textboxes%5B3%5D.png"&gt;&lt;img height="201" width="189" src="http://lh5.ggpht.com/_7YCdMP8inuc/TApTbKKeF3I/AAAAAAAAAD0/JH-46hutuhE/textboxes_thumb%5B1%5D.png?imgmax=800" alt="textboxes" border="0" title="textboxes" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;El c&amp;oacute;digo xaml del objeto ScrollViewer es este:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ScrollViewer x:Name=&amp;quot;PART_ContentHost&amp;quot; 
Opacity=&amp;quot;.7&amp;quot; 
Content=&amp;quot;{Binding Path=Content, 
RelativeSource={RelativeSource TemplatedParent}}&amp;quot; 
HorizontalAlignment=&amp;quot;{Binding Path=HorizontalAlignment, 
RelativeSource={RelativeSource TemplatedParent}}&amp;quot; 
VerticalAlignment=&amp;quot;{Binding Path=VerticalAlignment, 
RelativeSource={RelativeSource TemplatedParent}}&amp;quot; 
Width=&amp;quot;{Binding Path=Width, 
RelativeSource={RelativeSource TemplatedParent}}&amp;quot; 
Height=&amp;quot;{Binding Path=Height, 
RelativeSource={RelativeSource TemplatedParent}}&amp;quot;&amp;gt;
&amp;lt;/ScrollViewer&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;En este caso salvo la Opacity del ScrollViewer, el resto de propiedades (Content, HorizontalAlignment, VerticalAlignment, Width y Height) se han enlazado al control padre de la plantilla para ilustrar que cualquier propiedad compartida entre un control de la plantilla y el control padre puede ser enlazada.&lt;/div&gt;
&lt;div align="justify"&gt;En este caso, el nombre definido al ScrollViewer no es al azar, este control tiene c&amp;oacute;digo enlazado con el ScrollViewer en su plantilla original, esta es una peque&amp;ntilde;a limitaci&amp;oacute;n y una de las pocas que encontraremos, para que todo siga funcionando correctamente, debemos respetar el nombre, en este caso PART_ContentHost. Microsoft recomienda que siempre que tengamos que usar c&amp;oacute;digo contra un objeto parte de una plantilla lo llamemos PART_xxxxxxxx para de esta forma seguir una nomenclatura com&amp;uacute;n.&lt;/div&gt;
&lt;div align="justify"&gt;En este caso los Triggers usados son m&amp;aacute;s sencillos que los del bot&amp;oacute;n, usamos 2 EventTrigger LostFocus y GotFocus y un Trigger a la propiedad IsEnabled:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate.Triggers&amp;gt;
&amp;lt;EventTrigger RoutedEvent=&amp;quot;TextBox.LostFocus&amp;quot;&amp;gt;
&amp;lt;EventTrigger.Actions&amp;gt;
&amp;lt;BeginStoryboard Storyboard=&amp;quot;{StaticResource GlowOut}&amp;quot;&amp;gt;
&amp;lt;/BeginStoryboard&amp;gt;
&amp;lt;/EventTrigger.Actions&amp;gt;
&amp;lt;/EventTrigger&amp;gt;
&amp;lt;EventTrigger RoutedEvent=&amp;quot;TextBox.GotFocus&amp;quot;&amp;gt;
&amp;lt;EventTrigger.Actions&amp;gt;
&amp;lt;BeginStoryboard Storyboard=&amp;quot;{StaticResource GlowIn}&amp;quot;&amp;gt;
&amp;lt;/BeginStoryboard&amp;gt;
&amp;lt;/EventTrigger.Actions&amp;gt;
&amp;lt;/EventTrigger&amp;gt;
&amp;lt;Trigger Property=&amp;quot;IsEnabled&amp;quot; Value=&amp;quot;False&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Opacity&amp;quot; TargetName=&amp;quot;PART_ContentHost&amp;quot; 
Value=&amp;quot;.3&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Opacity&amp;quot; TargetName=&amp;quot;BorderExtern&amp;quot; 
Value=&amp;quot;.5&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Fill&amp;quot; TargetName=&amp;quot;GlassRectangle&amp;quot; 
Value=&amp;quot;{StaticResource GlassFXDisabled}&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;/Trigger&amp;gt;
&amp;lt;/ControlTemplate.Triggers&amp;gt;&lt;/pre&gt;
&lt;h3&gt;Scrollbars&lt;/h3&gt;
&lt;p&gt;El control scrollbar nos va a dar algo m&amp;aacute;s de trabajo que los dos primeros controles, pues involucra partes m&amp;oacute;viles y puede cambiar de orientaci&amp;oacute;n, de vertical a horizontal. &lt;/p&gt;
&lt;div align="center"&gt;&lt;a href="http://lh5.ggpht.com/_7YCdMP8inuc/TApTcOBudoI/AAAAAAAAAD4/7vZ9a2lnZ0A/s1600-h/Scrollbars%5B3%5D.png"&gt;&lt;img height="200" width="155" src="http://lh3.ggpht.com/_7YCdMP8inuc/TApTc4qJXsI/AAAAAAAAAD8/HsoZD1h9plk/Scrollbars_thumb%5B1%5D.png?imgmax=800" alt="Scrollbars" border="0" title="Scrollbars" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;Para este control Debemos definir varios estilos por separado y controltemplates independientes, uno para la barra vertical y otro para la barra horizontal.&lt;/div&gt;
&lt;p&gt;Primero empezaremos definiendo los estilos de los controles que componen un scrollbar, LineButtons, PageButtons y ScrollThumb: &lt;/p&gt;
&lt;div align="center"&gt;&lt;a href="http://lh4.ggpht.com/_7YCdMP8inuc/TApTdtrnEuI/AAAAAAAAAEA/aYPp311LewI/s1600-h/scrollbar_parts%5B4%5D.png"&gt;&lt;img height="143" width="187" src="http://lh5.ggpht.com/_7YCdMP8inuc/TApTeeNlTcI/AAAAAAAAAEE/09bfc5oBOqs/scrollbar_parts_thumb%5B2%5D.png?imgmax=800" alt="scrollbar_parts" border="0" title="scrollbar_parts" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;h5&gt;&lt;/h5&gt;
&lt;h5&gt;LineButton:&lt;/h5&gt;
&lt;div align="justify"&gt;Los LineButtons son los botones en los extremos del scrollbar, el tipo de control es repeatbutton y su controltemplate es muy sencillo:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate x:Name=&amp;quot;tmplRepeatButton&amp;quot;&amp;gt;
&amp;lt;Border Background=&amp;quot;#FF222222&amp;quot; BorderBrush=&amp;quot;DarkBlue&amp;quot; 
BorderThickness=&amp;quot;1&amp;quot; CornerRadius=&amp;quot;3&amp;quot;&amp;gt;
&amp;lt;Path HorizontalAlignment=&amp;quot;Center&amp;quot; 
VerticalAlignment=&amp;quot;Center&amp;quot; 
Data=&amp;quot;{Binding Path=Content,
RelativeSource={RelativeSource TemplatedParent}}&amp;quot; 
Fill=&amp;quot;Cyan&amp;quot; &amp;gt;
&amp;lt;/Path&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Se compone solo de dos controles, un Border que define el aspecto del control, y contiene un objeto Path, cuya propiedad Data asociamos a la propiedad Content del control al que a&amp;ntilde;adiremos esta plantilla. La gran potencia del objeto Path viene dada por su propiedad Data, pues dispone de un &amp;ldquo;mini lenguaje&amp;rdquo; para especificar geometr&amp;iacute;as complejas de una forma r&amp;aacute;pida y sencilla. Pod&amp;eacute;is encontrar una referencia muy completa en msdn &lt;a target="_blank" rel="nofollow" href="http://msdn.microsoft.com/en-us/library/ms752293.aspx"&gt;aqu&amp;iacute;.&lt;/a&gt;&lt;/div&gt;
&lt;div align="justify"&gt;Su nombre viene indicado por la acci&amp;oacute;n que realiza, pues cada vez que se pulsa un LineButton se avanza o retrocede una linea del control que estemos usando.&lt;/div&gt;
&lt;h5&gt;PageButtons:&lt;/h5&gt;
&lt;div align="justify"&gt;Los page buttons act&amp;uacute;an como el fondo de la barra sobre la que desplazamos el scrollbar, como su nombre indica son los encargados de mover adelante o atr&amp;aacute;s una p&amp;aacute;gina completa, el tipo de control es tambi&amp;eacute;n repeatbutton.&lt;/div&gt;
&lt;div align="justify"&gt;Su control template es muy sencillo y se compone de un solo objeto Border:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate x:Name=&amp;quot;tmplRepeatButton&amp;quot;&amp;gt;
&amp;lt;Border Background=&amp;quot;#66000000&amp;quot; BorderBrush=&amp;quot;Black&amp;quot; 
BorderThickness=&amp;quot;1&amp;quot; CornerRadius=&amp;quot;3&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Como pod&amp;eacute;is ver, tanto el template del LineButton como el del PageButton tienen el mismo nombre, esto se debe a que al ser plantillas incrustadas dentro de un estilo, su &amp;aacute;mbito es el estilo y no colisionan entre s&amp;iacute;.&lt;/div&gt;
&lt;h5&gt;ScrollThumb:&lt;/h5&gt;
&lt;div align="justify"&gt;El scrollthumb es la parte m&amp;oacute;vil del scrollbar, se redimensiona a medida que es necesario m&amp;aacute;s scroll o menos y podemos pincharlo y arrastrarlo para movernos por el contenido, el tipo de control usado es Thumb, puesto que incluye funcionalidad para Drag&amp;amp;Drop de forma nativa, su control template tambi&amp;eacute;n es algo m&amp;aacute;s complejo que los anteriores botones:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate x:Name=&amp;quot;tmplScrollThumb&amp;quot;&amp;gt;
&amp;lt;Grid&amp;gt;
&amp;lt;Rectangle RadiusX=&amp;quot;3&amp;quot; RadiusY=&amp;quot;3&amp;quot; Fill=&amp;quot;#66222222&amp;quot;&amp;gt;
&amp;lt;/Rectangle&amp;gt;
&amp;lt;Border CornerRadius=&amp;quot;3&amp;quot; BorderBrush=&amp;quot;DarkBlue&amp;quot; 
Background=&amp;quot;{StaticResource GlassFX}&amp;quot;&amp;gt;
&amp;lt;Path HorizontalAlignment=&amp;quot;Center&amp;quot; 
VerticalAlignment=&amp;quot;Center&amp;quot; 
Data=&amp;quot;{Binding Path=Content,
RelativeSource={RelativeSource TemplatedParent}}&amp;quot;&amp;gt;
&amp;lt;/Path&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;/Grid&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Tenemos una grid que contendr&amp;aacute; nuestros controles, un rect&amp;aacute;ngulo que act&amp;uacute;a como fondo base del Thumb. un Border para darle el efecto de cristal y dentro de este un objeto Path para que podamos incluir una geometr&amp;iacute;a personalizada si lo deseamos.&lt;/div&gt;
&lt;div align="justify"&gt;&lt;/div&gt;
&lt;div align="justify"&gt;Ahora que ya hemos definido las plantillas y estilos de nuestros controles base, podemos pasar a definir las plantillas de las Scrollbar tanto vertical como Horizontal:&lt;/div&gt;
&lt;h5&gt;Scrollbar vertical:&lt;/h5&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate x:Key=&amp;quot;VerticalScroll&amp;quot; TargetType=&amp;quot;{x:Type ScrollBar}&amp;quot;&amp;gt;
&amp;lt;Grid&amp;gt;
&amp;lt;Grid.RowDefinitions&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;18&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;0.00001*&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;18&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;/Grid.RowDefinitions&amp;gt;
&amp;lt;Border Grid.RowSpan=&amp;quot;3&amp;quot; CornerRadius=&amp;quot;3&amp;quot; 
BorderBrush=&amp;quot;DarkBlue&amp;quot; BorderThickness=&amp;quot;1&amp;quot; 
Opacity=&amp;quot;.6&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;RepeatButton Grid.Row=&amp;quot;0&amp;quot; 
Style=&amp;quot;{StaticResource LineButton}&amp;quot; 
Height=&amp;quot;18&amp;quot; Command=&amp;quot;ScrollBar.LineUpCommand&amp;quot; 
Content=&amp;quot;M 0 4 L 8 4 L 4 0 Z&amp;quot;&amp;gt;
&amp;lt;/RepeatButton&amp;gt;
&amp;lt;Track Name=&amp;quot;PART_Track&amp;quot; Grid.Row=&amp;quot;1&amp;quot; IsDirectionReversed=&amp;quot;True&amp;quot;&amp;gt;
&amp;lt;Track.DecreaseRepeatButton&amp;gt;
&amp;lt;RepeatButton Style=&amp;quot;{StaticResource PageButton}&amp;quot; 
Command=&amp;quot;ScrollBar.PageUpCommand&amp;quot; /&amp;gt;
&amp;lt;/Track.DecreaseRepeatButton&amp;gt;
&amp;lt;Track.Thumb&amp;gt;
&amp;lt;Thumb Style=&amp;quot;{StaticResource ScrollThumb}&amp;quot; /&amp;gt;
&amp;lt;/Track.Thumb&amp;gt;
&amp;lt;Track.IncreaseRepeatButton&amp;gt;
&amp;lt;RepeatButton Style=&amp;quot;{StaticResource PageButton}&amp;quot; 
Command=&amp;quot;ScrollBar.PageDownCommand&amp;quot; /&amp;gt;
&amp;lt;/Track.IncreaseRepeatButton&amp;gt;
&amp;lt;/Track&amp;gt;
&amp;lt;RepeatButton Grid.Row=&amp;quot;2&amp;quot; 
Style=&amp;quot;{StaticResource LineButton}&amp;quot; 
Height=&amp;quot;18&amp;quot; Command=&amp;quot;ScrollBar.LineDownCommand&amp;quot; 
Content=&amp;quot;M 0 0 L 4 4 L 8 0 Z&amp;quot;&amp;gt;
&amp;lt;/RepeatButton&amp;gt;            
&amp;lt;/Grid&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Este ya es un control template m&amp;aacute;s complejo, compuesto de m&amp;aacute;s controles. Para empezar tenemos una grid a la que le definimos 3 Rows, la primera y la ultima contendr&amp;aacute;n los botones de subir y bajar usando repeatbuttons a los que les aplicamos el estilo que anteriormente creamos LineButton.&lt;/div&gt;
&lt;div align="justify"&gt;En la parte central de la grid definimos un objeto Track, puesto que esta parte de un scrollbar tiene c&amp;oacute;digo asociado le asignamos el mismo nombre que el del original: PART_Track y dentro del mismo tenemos 3 propiedades que debemos rellenar: DecreaseRepeatButton, Thumb e IncreaseRepeatButton. En el DecreaseRepeatButton e IncreaseRepeatButton definimos RepeatButtons con el estilo PageButton que creamos anteriormente y en Thumb definimos un control Thumb con el estilo ScrollThumb.&lt;/div&gt;
&lt;div align="justify"&gt;Algo a tener en cuenta es el Content de los RepeatButton usados con el estilo LineButton, estas combinaciones de letras y n&amp;uacute;meros son el &amp;ldquo;mini lenguaje&amp;rdquo; de geometr&amp;iacute;a que usa el objeto Path para dibujar formas, es muy &amp;uacute;til e interesante, en el apartado del estilo LineButton ten&amp;eacute;is un enlace a una descripci&amp;oacute;n completa de este lenguaje.&lt;/div&gt;
&lt;h5&gt;Scrollbar Horizontal:&lt;/h5&gt;
&lt;div align="justify"&gt;El scrollbar horizontal es id&amp;eacute;ntico al scrollbar vertical, solo que en vez de dividir la Grid en Rows la dividimos en Columnas, usando la primera y ultima columna para los LineButtons y la columna central para el Track:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate x:Key=&amp;quot;HorizontalScroll&amp;quot; TargetType=&amp;quot;{x:Type ScrollBar}&amp;quot;&amp;gt;
&amp;lt;Grid&amp;gt;
&amp;lt;Grid.ColumnDefinitions&amp;gt;
&amp;lt;ColumnDefinition Width=&amp;quot;18&amp;quot;&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
&amp;lt;ColumnDefinition Width=&amp;quot;0.00001*&amp;quot;&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
&amp;lt;ColumnDefinition Width=&amp;quot;18&amp;quot;&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
&amp;lt;/Grid.ColumnDefinitions&amp;gt;
&amp;lt;Border Grid.ColumnSpan=&amp;quot;3&amp;quot; CornerRadius=&amp;quot;3&amp;quot; 
BorderBrush=&amp;quot;DarkBlue&amp;quot; BorderThickness=&amp;quot;1&amp;quot; 
Opacity=&amp;quot;.6&amp;quot; &amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;RepeatButton Grid.Column=&amp;quot;0&amp;quot; 
Style=&amp;quot;{StaticResource LineButton}&amp;quot; 
Width=&amp;quot;18&amp;quot; Command=&amp;quot;ScrollBar.LineLeftCommand&amp;quot; 
Content=&amp;quot;M 4 0 L 4 8 L 0 4 Z&amp;quot;&amp;gt;
&amp;lt;/RepeatButton&amp;gt;
&amp;lt;Track Name=&amp;quot;PART_Track&amp;quot; Grid.Column=&amp;quot;1&amp;quot; IsDirectionReversed=&amp;quot;False&amp;quot;&amp;gt;
&amp;lt;Track.DecreaseRepeatButton&amp;gt;
&amp;lt;RepeatButton Style=&amp;quot;{StaticResource PageButton}&amp;quot; 
Command=&amp;quot;ScrollBar.PageLeftCommand&amp;quot; /&amp;gt;
&amp;lt;/Track.DecreaseRepeatButton&amp;gt;
&amp;lt;Track.Thumb&amp;gt;
&amp;lt;Thumb Style=&amp;quot;{StaticResource ScrollThumb}&amp;quot; /&amp;gt;
&amp;lt;/Track.Thumb&amp;gt;
&amp;lt;Track.IncreaseRepeatButton&amp;gt;
&amp;lt;RepeatButton Style=&amp;quot;{StaticResource PageButton}&amp;quot; 
Command=&amp;quot;ScrollBar.PageRightCommand&amp;quot; /&amp;gt;
&amp;lt;/Track.IncreaseRepeatButton&amp;gt;
&amp;lt;/Track&amp;gt;
&amp;lt;RepeatButton Grid.Column=&amp;quot;2&amp;quot; 
Style=&amp;quot;{StaticResource LineButton}&amp;quot;
Width=&amp;quot;18&amp;quot; Command=&amp;quot;ScrollBar.LineRightCommand&amp;quot;
Content=&amp;quot;M 0 0 L 4 4 L 0 8 Z&amp;quot;&amp;gt;
&amp;lt;/RepeatButton&amp;gt;
&amp;lt;/Grid&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Por &amp;uacute;ltimo solo nos queda definir un estilo com&amp;uacute;n para el control Scrollbar que decida que plantilla aplicar dependiendo de la orientaci&amp;oacute;n designada por el control:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Style TargetType=&amp;quot;{x:Type ScrollBar}&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;OverridesDefaultStyle&amp;quot; Value=&amp;quot;True&amp;quot; /&amp;gt;
&amp;lt;Setter Property=&amp;quot;SnapsToDevicePixels&amp;quot; Value=&amp;quot;True&amp;quot; /&amp;gt;
&amp;lt;Style.Triggers&amp;gt;
&amp;lt;Trigger Property=&amp;quot;Orientation&amp;quot; Value=&amp;quot;Vertical&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Width&amp;quot; Value=&amp;quot;18&amp;quot;&amp;gt;&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Height&amp;quot; Value=&amp;quot;Auto&amp;quot;&amp;gt;&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Template&amp;quot; Value=&amp;quot;{StaticResource VerticalScroll}&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;/Trigger&amp;gt;
&amp;lt;Trigger Property=&amp;quot;Orientation&amp;quot; Value=&amp;quot;Horizontal&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Width&amp;quot; Value=&amp;quot;Auto&amp;quot;&amp;gt;&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Height&amp;quot; Value=&amp;quot;18&amp;quot;&amp;gt;&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Template&amp;quot; Value=&amp;quot;{StaticResource HorizontalScroll}&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;/Trigger&amp;gt;            
&amp;lt;/Style.Triggers&amp;gt;
&amp;lt;/Style&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Este es un estilo sencillo, simplemente tenemos dos Triggers que controlan la propiedad Orientation, y dependiendo de su valor aplican una plantilla u otra.&lt;/div&gt;
&lt;h3&gt;ProgressBar&lt;/h3&gt;
&lt;div align="justify"&gt;La barra de progreso es un control muy &amp;uacute;til para ofrecer informaci&amp;oacute;n al usuario a cerca de la realizaci&amp;oacute;n de una tarea que se alarga en el tiempo un poco. En este caso a parte de darle una apariencia m&amp;aacute;s atractiva tambi&amp;eacute;n vamos a darle un toque m&amp;aacute;s de funcionalidad, permitiendo indicar al usuario el porcentaje del trabajo realizado de forma num&amp;eacute;rica. Tambi&amp;eacute;n tenemos soporte para trabajos con duraci&amp;oacute;n indeterminada:&lt;/div&gt;
&lt;div align="center"&gt;&lt;a href="http://lh3.ggpht.com/_7YCdMP8inuc/TApTe0PB1sI/AAAAAAAAAEI/i1RAEPzIIuM/s1600-h/progressbar%5B3%5D.png"&gt;&lt;img height="180" width="203" src="http://lh6.ggpht.com/_7YCdMP8inuc/TApTflN9PKI/AAAAAAAAAEM/-QFoOtqkkPk/progressbar_thumb%5B1%5D.png?imgmax=800" alt="progressbar" border="0" title="progressbar" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;En la imagen superior podemos ver 3 estados de una ProgressBar: Determinado, Indeterminado y Desactivado. Como pod&amp;eacute;is ver en los estados Determinado y desactivado se ofrece una informaci&amp;oacute;n visual del % realizado en forma de n&amp;uacute;mero.&lt;/div&gt;
&lt;p&gt;El Control template es muy parecido al de cualquier otro control que hayamos visto: &lt;/p&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate TargetType=&amp;quot;{x:Type ProgressBar}&amp;quot;&amp;gt;
&amp;lt;Grid MinHeight=&amp;quot;14&amp;quot; MinWidth=&amp;quot;20&amp;quot;&amp;gt;
&amp;lt;Border x:Name=&amp;quot;BaseRectangle&amp;quot; 
Background=&amp;quot;{StaticResource BaseColor}&amp;quot; 
CornerRadius=&amp;quot;10,0,10,0&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;GlassRectangle&amp;quot; CornerRadius=&amp;quot;10,0,10,0&amp;quot;  
Background=&amp;quot;{StaticResource GlassFX}&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;animation&amp;quot; CornerRadius=&amp;quot;10,0,10,0&amp;quot; 
Opacity=&amp;quot;.7&amp;quot; Background=&amp;quot;{StaticResource GlowFXProgress}&amp;quot; 
HorizontalAlignment=&amp;quot;Left&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;PART_Indicator&amp;quot; CornerRadius=&amp;quot;10,0,10,0&amp;quot; 
Background=&amp;quot;{StaticResource GlowFXProgress}&amp;quot; 
HorizontalAlignment=&amp;quot;Left&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;PART_Track&amp;quot; BorderThickness=&amp;quot;1&amp;quot; 
CornerRadius=&amp;quot;10,0,10,0&amp;quot; BorderBrush=&amp;quot;Black&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;BordeCabeceraSombra&amp;quot; BorderThickness=&amp;quot;2&amp;quot; 
CornerRadius=&amp;quot;10,0,10,0&amp;quot; BorderBrush=&amp;quot;DarkGray&amp;quot; 
Opacity=&amp;quot;.2&amp;quot; Margin=&amp;quot;1,1,1,0&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Label x:Name=&amp;quot;Progress&amp;quot; VerticalAlignment=&amp;quot;Stretch&amp;quot; 
HorizontalAlignment=&amp;quot;Stretch&amp;quot; 
HorizontalContentAlignment=&amp;quot;Center&amp;quot; 
VerticalContentAlignment=&amp;quot;Center&amp;quot; 
FontWeight=&amp;quot;Bold&amp;quot; Foreground=&amp;quot;White&amp;quot; Opacity=&amp;quot;.7&amp;quot; 
Content=&amp;quot;{Binding Path=Value, 
RelativeSource={RelativeSource TemplatedParent}}&amp;quot;&amp;gt;
&amp;lt;/Label&amp;gt;
&amp;lt;/Grid&amp;gt;
&amp;lt;ControlTemplate.Triggers&amp;gt;
&amp;lt;Trigger Property=&amp;quot;IsIndeterminate&amp;quot; Value=&amp;quot;True&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Visibility&amp;quot; TargetName=&amp;quot;Progress&amp;quot; Value=&amp;quot;Hidden&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Background&amp;quot; TargetName=&amp;quot;PART_Indicator&amp;quot;&amp;gt;
&amp;lt;Setter.Value&amp;gt;
&amp;lt;MultiBinding&amp;gt;
&amp;lt;MultiBinding.Converter&amp;gt;
&amp;lt;wintheme:ProgressBarHighlightConverter/&amp;gt;
&amp;lt;/MultiBinding.Converter&amp;gt;
&amp;lt;Binding Source=&amp;quot;{StaticResource GlowFXProgressAnimated}&amp;quot;/&amp;gt;
&amp;lt;Binding Path=&amp;quot;ActualWidth&amp;quot;  ElementName=&amp;quot;BaseRectangle&amp;quot;/&amp;gt;
&amp;lt;Binding Path=&amp;quot;ActualHeight&amp;quot; ElementName=&amp;quot;BaseRectangle&amp;quot;/&amp;gt;
&amp;lt;/MultiBinding&amp;gt;
&amp;lt;/Setter.Value&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;/Trigger&amp;gt;
&amp;lt;Trigger Property=&amp;quot;IsEnabled&amp;quot; Value=&amp;quot;False&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Opacity&amp;quot; Value=&amp;quot;.5&amp;quot;&amp;gt;&amp;lt;/Setter&amp;gt;
&amp;lt;/Trigger&amp;gt;
&amp;lt;/ControlTemplate.Triggers&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Esta plantilla es larga pero no es complicada, lo m&amp;aacute;s interesante de la misma se encuentra en dos puntos, primero, el control label que compone la plantilla, cuyo contenido est&amp;aacute; enlazado a la propiedad Value de la progressbar, de esta forma siempre que cambie la propiedad value se reflejar&amp;aacute; en el control label.&lt;/div&gt;
&lt;div align="justify"&gt;El segundo se encuentra en el Trigger que controla cuando la propiedad IsIndeterminate es verdadera, cambiamos el valor de la propiedad background del control PART_Indicator usando un Multibinding Converter, esto es una clase que acepta varios valores de entrada y devuelve un valor de salida. En nuestro caso queremos conservar la funcionalidad de Windows Vista y 7 en las barras indeterminadas, para ello debemos incluir en nuestro proyecto una referencia al ensamblado: &lt;strong&gt;PressentationFramework.Aero&lt;/strong&gt; y referenciarlo en el archivo xaml de nuestro tema de la siguiente forma:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;xmlns:wintheme=&amp;quot;clr-namespace:Microsoft.Windows.Themes;
assembly=PresentationFramework.Aero&amp;quot;&lt;/pre&gt;
&lt;p&gt;Con esto nuestra progressbar funcionar&amp;aacute; perfectamente. &lt;/p&gt;
&lt;h3&gt;Conclusi&amp;oacute;n&lt;/h3&gt;
&lt;p&gt;El tema Black Crystal incluye otros controles como son Datagrid, TabControl y GroupBox. Os dejo como tarea para casa el analizarlos, con lo visto aqu&amp;iacute; ver&amp;eacute;is que no es complicado comprenderlos. Un gran saludo y Happy Coding!&lt;/p&gt;
&lt;p&gt;&lt;a href="http://cid-fd100135b82f3364.skydrive.live.com/embedicon.aspx/.Public/ejemplos/NET%204%20WPF%20Estilos"&gt;&lt;span style="background: SpringGreen;"&gt;Descargar&lt;/span&gt; &lt;span style="background: SpringGreen;"&gt;c&lt;/span&gt;&lt;span style="background: SpringGreen;"&gt;&amp;oacute;digo&lt;/span&gt;&lt;/a&gt;&lt;/p&gt;</description></item><item><title>WPF: Personalizar nuestra aplicación con Styles y Control Templates (II)</title><link>http://geeks.ms/wikis/wpf/wpf-personalizar-nuestra-aplicaci-243-n-con-styles-y-control-templates-ii/revision/1.aspx</link><pubDate>Mon, 26 Jul 2010 04:34:17 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:17</guid><dc:creator>Josué Yeray Julián Ferreiro</dc:creator><description>Revisión 1 enviado a Wiki sobre WPF en Geeks•ms por Josué Yeray Julián Ferreiro a 7/26/2010 6:34:17 AM&lt;br /&gt;
&lt;div align="justify"&gt;En la primera parte de este art&amp;iacute;culo aprendimos las distintas formas que nos ofrece WPF para personalizar nuestros controles, centr&amp;aacute;ndonos en los estilos y las plantillas de control. Le dimos un repaso a la teor&amp;iacute;a b&amp;aacute;sica sobre elementos comunes y diccionarios de recursos.&lt;/div&gt;
&lt;div align="justify"&gt;&lt;/div&gt;
&lt;!--more--&gt;
&lt;div align="justify"&gt;&lt;/div&gt;
&lt;div align="justify"&gt;&lt;/div&gt;
&lt;div align="justify"&gt;Si te lo perdiste o quieres darle un repaso aqu&amp;iacute; lo tienes:&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;WPF&lt;a href="/wikis/wpf/wpf-personalizar-nuestra-aplicaci-243-n-con-styles-y-control-templates-i.aspx"&gt;: Personalizar nuestra aplicaci&amp;oacute;n con Styles y Control Templates (I) &lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;div align="justify"&gt;Esta vez vamos a ir directamente al meollo de la cuesti&amp;oacute;n, examinando a fondo como personalizar varios controles est&amp;aacute;ndar de WPF como son los siguientes:&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Button &lt;/li&gt;
&lt;li&gt;Textbox &lt;/li&gt;
&lt;li&gt;Scrollbars (Horizontales y Verticales) &lt;/li&gt;
&lt;li&gt;ProgressBar &lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;Button&lt;/h3&gt;
&lt;div align="justify"&gt;El bot&amp;oacute;n es uno de los controles m&amp;aacute;s sencillos de personalizar, pero a su vez es uno de los controles m&amp;aacute;s &amp;uacute;tiles y el usuario interact&amp;uacute;a mucho con ellos, por lo que es importante hacerlos lo m&amp;aacute;s atractivos que podamos:&lt;/div&gt;
&lt;div align="center"&gt;&lt;a href="http://lh5.ggpht.com/_7YCdMP8inuc/TApTZLASV6I/AAAAAAAAADo/N5o_BEHPahA/s1600-h/botones7.png"&gt;&lt;img height="203" width="153" src="http://lh5.ggpht.com/_7YCdMP8inuc/TApTZlikVRI/AAAAAAAAADs/IZDIl_X6BHU/botones_thumb5.png?imgmax=800" alt="botones" border="0" title="botones" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;Algo muy importante a recordar cuando creamos nuestras propias plantillas es que estas substituyen completamente la plantilla por defecto del control, por lo que si queremos dar indicaciones visuales de que nuestro bot&amp;oacute;n est&amp;aacute; activado, desactivado, pulsado, con foco o con el rat&amp;oacute;n sobre el, deberemos hacerlo nosotros, esto lo lograremos aprovech&amp;aacute;ndonos de los Triggers del control.&lt;/div&gt;
&lt;div align="justify"&gt;Lo primero que vamos a hacer es definir un estilo nuevo para todos los controles del tipo Button, pues no queremos aplicarlo de forma selectiva a ciertos botones, queremos que sea la apariencia predeterminada de cualquier bot&amp;oacute;n en nuestra aplicaci&amp;oacute;n:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Style TargetType=&amp;quot;{x:Type Button}&amp;quot;&amp;gt;

&amp;lt;/Style&amp;gt;&lt;/pre&gt;
&lt;p&gt;Simplemente en la cabecera Style definimos la propiedad TargetType al tipo Button. Ahora vamos a incluir algunas propiedades por defecto para nuestro bot&amp;oacute;n dentro de este bloque Style: &lt;/p&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Setter Property=&amp;quot;OverridesDefaultStyle&amp;quot; Value=&amp;quot;True&amp;quot; /&amp;gt;
&amp;lt;Setter Property=&amp;quot;SnapsToDevicePixels&amp;quot; Value=&amp;quot;True&amp;quot; /&amp;gt;
&amp;lt;Setter Property=&amp;quot;Foreground&amp;quot; Value=&amp;quot;White&amp;quot; /&amp;gt; &lt;/pre&gt;
&lt;div align="justify"&gt;El objeto Setter es muy sencillo, simplemente tiene el atributo Property que especifica el nombre de la propiedad que queremos establecer y el atributo Value que especifica el valor a aplicar en esa propiedad. La propiedad &lt;strong&gt;OverridesDefaultStyle&lt;/strong&gt; indica a nuestro control que nunca se usar&amp;aacute; el tema por defecto del control para ninguna propiedad, aunque esta no est&amp;eacute; definida en nuestro estilo o plantilla, si no hemos implementado algo, es porque no lo necesitamos o lo suplimos de alguna otra forma. &lt;strong&gt;SnapsToDevicePixels&lt;/strong&gt; indica a nuestro estilo que el dibujado de nuestro control debe usar pixeles dependientes del dispositivo. Por defecto WPF usa el DPI actual para obtener independencia de la resoluci&amp;oacute;n a la hora de dibujar, pero esto puede causar un efecto difuso o borroso, y en nuestro caso queremos que nuestros preciosos controles se vean bien, por lo que indicando esta propiedad evitaremos este dibujado difuso o borroso. &lt;strong&gt;Foreground&lt;/strong&gt;, bueno no hay mucho que decir, en el caso de nuestro bot&amp;oacute;n la propiedad Foreground afecta al texto del mismo. Puesto que nuestro bot&amp;oacute;n es oscuro y por defecto el texto es de color negro, ser&amp;iacute;a un incordio estar recorriendo todos los botones cambiando el texto a Blanco u otro color y precisamente queremos que modificar el aspecto de nuestra aplicaci&amp;oacute;n se haga de forma centralizada, por lo que al incluir esta propiedad todos los botones obtendr&amp;aacute;n texto blanco.&lt;/div&gt;
&lt;div align="justify"&gt;El &amp;uacute;ltimo objeto Setter que necesitamos establecer&amp;aacute; la propiedad Template del bot&amp;oacute;n y dentro de este Setter definiremos nuestro Control Template:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Setter Property=&amp;quot;Template&amp;quot;&amp;gt;
&amp;lt;Setter.Value&amp;gt;
&amp;lt;ControlTemplate x:Name=&amp;quot;tmpltButton&amp;quot;&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;
&amp;lt;/Setter.Value&amp;gt;
&amp;lt;/Setter&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;A diferencia del estilo, que establecia su propiedad TargetType, en el ControlTemplate establecemos x:Name pues esta contenido dentro del estilo y se aplicar&amp;aacute; autom&amp;aacute;ticamente all&amp;iacute; donde se aplique el estilo.&lt;/div&gt;
&lt;div align="justify"&gt;Dentro del objeto ControlTemplate podemos empezar a definir nuestro bot&amp;oacute;n, aqu&amp;iacute; es donde WPF te golpea con un derroche de realidad: ControlTemplate es una pizarra en blanco en la que puedes pintar TODO lo que tu quieras y el resultado final, ser&amp;aacute; el aspecto de tu bot&amp;oacute;n, no hay reglas (o no demasiadas), solo creatividad.&lt;/div&gt;
&lt;div align="justify"&gt;Nuestro bot&amp;oacute;n se va a componer de 6 controles b&amp;aacute;sicos: 1 Grid para mantener todo unido, 4 Borders para crear la forma y relleno y 1 ContentPresenter que presentar&amp;aacute; el contenido del bot&amp;oacute;n, quedar&amp;iacute;a algo as&amp;iacute;:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Grid&amp;gt;
&amp;lt;Border x:Name=&amp;quot;BaseRectangle&amp;quot; 
Background=&amp;quot;{StaticResource BaseColor}&amp;quot; 
CornerRadius=&amp;quot;10,0,10,0&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;GlassRectangle&amp;quot; 
Background=&amp;quot;{StaticResource GlassFX}&amp;quot; 
CornerRadius=&amp;quot;10,0,10,0&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;GlowRectangle&amp;quot; 
Background=&amp;quot;{StaticResource GlowFX}&amp;quot; 
CornerRadius=&amp;quot;10,0,10,0&amp;quot; 
Opacity=&amp;quot;0&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;ButtonBorder&amp;quot; 
CornerRadius=&amp;quot;10,0,10,0&amp;quot; 
BorderBrush=&amp;quot;Black&amp;quot; 
Opacity=&amp;quot;1&amp;quot;  
BorderThickness=&amp;quot;1&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;ContentPresenter x:Name=&amp;quot;ButtonContent&amp;quot; 
Opacity=&amp;quot;.7&amp;quot; 
Content=&amp;quot;{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}&amp;quot; 
HorizontalAlignment=&amp;quot;center&amp;quot; 
VerticalAlignment=&amp;quot;center&amp;quot;&amp;gt;
&amp;lt;/ContentPresenter&amp;gt;
&amp;lt;/Grid&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Simplemente tenemos un grid que contiene nuestros controles Border y el ContentPresenter, el primer Border BaseRectangle es nuestra capa base de pintura, como veis todos los colores se definen con enlace a recursos que ya establecimos en nuestro diccionario de recursos, de esta forma si cambiamos el color BaseColor, cambiar&amp;aacute; en todos los sitios donde est&amp;eacute; aplicado. Todos los Border comparten el mismo valor de CornerRadius para que el control tenga la apariencia deseada, los 4 valores de CornerRadius siguen el orden de las agujas del reloj: &lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div align="justify"&gt;Esquina Superior Derecha&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;Esquina Superior Izquierda&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;Esquina Inferior Izquierda&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;Esquina Inferior Derecha&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div align="justify"&gt;Aplicando un valor de 10 en las esquinas superior derecha e inferior izquierda y un valor de 0 en las otras conseguimos el efecto deseado.&lt;/div&gt;
&lt;div align="justify"&gt;La propiedad Background de los dos primeros Border define la apariencia general de nuestro bot&amp;oacute;n, el primero aplicando un color base (nuestro recurso BaseColor) y el segundo aplicando un degradado llamado GlassFX que es el encargado de darle a nuestro bot&amp;oacute;n el efecto de reflejo de cristal.&lt;/div&gt;
&lt;div align="justify"&gt;El tercer Border define en el background el recurso GlowFX y es el usado para la animaci&amp;oacute;n del foco del bot&amp;oacute;n, por defecto establecemos su Opacity a 0, para animar esta propiedad m&amp;aacute;s adelante con los Event Triggers de nuestra plantilla.&lt;/div&gt;
&lt;div align="justify"&gt;El &amp;uacute;ltimo Border define el borde externo del bot&amp;oacute;n, en este caso no definimos la propiedad Background por lo que es transparente pero definimos la propiedad BorderBrush que establece el color del borde y BorderThickness que establece el grosor del borde.&lt;/div&gt;
&lt;div align="justify"&gt;La apariencia de nuestro bot&amp;oacute;n ya est&amp;aacute; casi completa, solo necesitamos mostrar el contenido que tenga cada bot&amp;oacute;n, ya sea texto, im&amp;aacute;genes o cualquier combinaci&amp;oacute;n de ambos, para esto usamos el control ContentPresenter. La propiedad m&amp;aacute;s interesante en el es Content, la enlazamos directamente al Content establecido en nuestro bot&amp;oacute;n:&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;div align="justify"&gt;Binding Path= Indica la propiedad a la que queremos enlazarnos.&lt;/div&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;div align="justify"&gt;RelativeSource= Indica la fuente de esta propiedad, en nuestro caso la dirigimos a una fuente relativa de tipo templatedparent, es decir el objeto padre de nuestra plantilla, que en este caso ser&amp;aacute; cada bot&amp;oacute;n que la use.&lt;/div&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;div align="justify"&gt;Con esto ya est&amp;aacute; totalmente terminada la apariencia de nuestro bot&amp;oacute;n. si colocamos un bot&amp;oacute;n en una ventana de pruebas veremos que usa nuestro estilo autom&amp;aacute;ticamente. Al ejecutar, no obstante, notaremos que el bot&amp;oacute;n no reacciona de ninguna manera al pasar el rat&amp;oacute;n sobre el o hacer click lo cual es muy poco intuitivo para el usuario final, esto lo resolveremos usando los Triggers del Controltemplate, justo despu&amp;eacute;s de la Grid, a&amp;ntilde;adimos un objeto ControlTemplate.Triggers:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate.Triggers&amp;gt;
&amp;lt;EventTrigger RoutedEvent=&amp;quot;Button.MouseLeave&amp;quot;&amp;gt;
&amp;lt;EventTrigger.Actions&amp;gt;
&amp;lt;BeginStoryboard Storyboard=&amp;quot;{StaticResource GlowOut}&amp;quot;&amp;gt;
&amp;lt;/BeginStoryboard&amp;gt;
&amp;lt;/EventTrigger.Actions&amp;gt;
&amp;lt;/EventTrigger&amp;gt;
&amp;lt;EventTrigger RoutedEvent=&amp;quot;Button.MouseEnter&amp;quot;&amp;gt;
&amp;lt;EventTrigger.Actions&amp;gt;
&amp;lt;BeginStoryboard Storyboard=&amp;quot;{StaticResource GlowIn}&amp;quot;&amp;gt;
&amp;lt;/BeginStoryboard&amp;gt;
&amp;lt;/EventTrigger.Actions&amp;gt;
&amp;lt;/EventTrigger&amp;gt;
&amp;lt;EventTrigger RoutedEvent=&amp;quot;Button.LostFocus&amp;quot;&amp;gt;
&amp;lt;EventTrigger.Actions&amp;gt;
&amp;lt;BeginStoryboard Storyboard=&amp;quot;{StaticResource GlowOut}&amp;quot;&amp;gt;
&amp;lt;/BeginStoryboard&amp;gt;
&amp;lt;/EventTrigger.Actions&amp;gt;
&amp;lt;/EventTrigger&amp;gt;
&amp;lt;EventTrigger RoutedEvent=&amp;quot;Button.GotFocus&amp;quot;&amp;gt;
&amp;lt;EventTrigger.Actions&amp;gt;
&amp;lt;BeginStoryboard Storyboard=&amp;quot;{StaticResource GlowIn}&amp;quot;&amp;gt;
&amp;lt;/BeginStoryboard&amp;gt;
&amp;lt;/EventTrigger.Actions&amp;gt;
&amp;lt;/EventTrigger&amp;gt;
&amp;lt;Trigger Property=&amp;quot;Button.IsPressed&amp;quot; Value=&amp;quot;True&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Background&amp;quot; TargetName=&amp;quot;GlowRectangle&amp;quot;
Value=&amp;quot;{StaticResource GlowFXPressed}&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Opacity&amp;quot; TargetName=&amp;quot;ButtonContent&amp;quot; 
Value=&amp;quot;1&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;/Trigger&amp;gt;
&amp;lt;Trigger Property=&amp;quot;IsEnabled&amp;quot; Value=&amp;quot;False&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Opacity&amp;quot; TargetName=&amp;quot;ButtonContent&amp;quot; 
Value=&amp;quot;.3&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Opacity&amp;quot; TargetName=&amp;quot;ButtonBorder&amp;quot; 
Value=&amp;quot;.5&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Background&amp;quot; TargetName=&amp;quot;GlassRectangle&amp;quot; 
Value=&amp;quot;{StaticResource GlassFXDisabled}&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;/Trigger&amp;gt;
&amp;lt;/ControlTemplate.Triggers&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Como pod&amp;eacute;is ver en este snippet, tenemos dos tipos de Triggers: Trigger y EventTrigger.&lt;/div&gt;
&lt;div align="justify"&gt;Los Trigger se disparan cuando la propiedad Indicada tiene el valor indicado, mientras que los EventTrigger se disparan cuando el evento indicado es lanzado. La mayor diferencia es que los EventTriggers nos permiten lanzar animaciones como indicaci&amp;oacute;n visual a un cambio en el estado del control. &lt;/div&gt;
&lt;div align="justify"&gt;En el caso de nuestro Bot&amp;oacute;n respondemos a 4 eventos: MouseEnter, MouseLeave, LostFocus y GotFocus. &lt;/div&gt;
&lt;div align="justify"&gt;Cada EventTrigger define un objeto EventTrigger.Actions y dentro de este encontramos el objeto BeginStoryboard, que inicia la animaci&amp;oacute;n indicada en su propiedad Storyboard (En el primer cap&amp;iacute;tulo ya hablamos sobre las animaciones y explicamos como crear animaciones sencillas).&lt;/div&gt;
&lt;div align="justify"&gt;Tambi&amp;eacute;n controlamos el cambio de 2 propiedades: IsPressed e IsEnabled.&lt;/div&gt;
&lt;div align="justify"&gt;Cada uno de estos 2 triggers se lanzar&amp;aacute; cuando la propiedad indicada tenga el valor indicado (Cuando IsPressed sea True y cuando IsEnabled sea false) y aplicar&amp;aacute; por medio de los objetos Setter valores a otras propiedades. Cada objeto Setter define Property que indica el nombre de la propiedad a modificar, TargetName que indica el nombre del objeto de nuestra plantilla al que afectar&amp;aacute; la modificaci&amp;oacute;n y value que indica el nuevo valor que tendr&amp;aacute; la propiedad.&lt;/div&gt;
&lt;div align="justify"&gt;Si volvemos a ejecutar nuestro proyecto comprobaremos que ahora gracias a los Triggers, nuestro bot&amp;oacute;n reacciona al pasar el rat&amp;oacute;n sobre el, al abandonarlo el rat&amp;oacute;n, al llegar a el con el tabulador o al salir de el, al presionarlo y al desactivarlo,con lo que conseguimos una respuesta visual muy importante para nuestro usuario final.&lt;/div&gt;
&lt;h3&gt;Textbox&lt;/h3&gt;
&lt;div align="justify"&gt;En general nuestro control Textbox se compone de forma muy parecida al Bot&amp;oacute;n, el mayor cambio en la composici&amp;oacute;n del control viene dado porque en este caso, en vez de usar un control ContentPresenter usaremos un control ScrollViewer, (que personalizaremos m&amp;aacute;s adelante tambi&amp;eacute;n) para permitir que el usuario pueda usar las barras de desplazamiento vertical y horizontal en una caja de texto multilinea:&lt;/div&gt;
&lt;div align="center"&gt;&lt;a href="http://lh4.ggpht.com/_7YCdMP8inuc/TApTaTg4k8I/AAAAAAAAADw/DQDg751WvAA/s1600-h/textboxes%5B3%5D.png"&gt;&lt;img height="201" width="189" src="http://lh5.ggpht.com/_7YCdMP8inuc/TApTbKKeF3I/AAAAAAAAAD0/JH-46hutuhE/textboxes_thumb%5B1%5D.png?imgmax=800" alt="textboxes" border="0" title="textboxes" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;El c&amp;oacute;digo xaml del objeto ScrollViewer es este:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ScrollViewer x:Name=&amp;quot;PART_ContentHost&amp;quot; 
Opacity=&amp;quot;.7&amp;quot; 
Content=&amp;quot;{Binding Path=Content, 
RelativeSource={RelativeSource TemplatedParent}}&amp;quot; 
HorizontalAlignment=&amp;quot;{Binding Path=HorizontalAlignment, 
RelativeSource={RelativeSource TemplatedParent}}&amp;quot; 
VerticalAlignment=&amp;quot;{Binding Path=VerticalAlignment, 
RelativeSource={RelativeSource TemplatedParent}}&amp;quot; 
Width=&amp;quot;{Binding Path=Width, 
RelativeSource={RelativeSource TemplatedParent}}&amp;quot; 
Height=&amp;quot;{Binding Path=Height, 
RelativeSource={RelativeSource TemplatedParent}}&amp;quot;&amp;gt;
&amp;lt;/ScrollViewer&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;En este caso salvo la Opacity del ScrollViewer, el resto de propiedades (Content, HorizontalAlignment, VerticalAlignment, Width y Height) se han enlazado al control padre de la plantilla para ilustrar que cualquier propiedad compartida entre un control de la plantilla y el control padre puede ser enlazada.&lt;/div&gt;
&lt;div align="justify"&gt;En este caso, el nombre definido al ScrollViewer no es al azar, este control tiene c&amp;oacute;digo enlazado con el ScrollViewer en su plantilla original, esta es una peque&amp;ntilde;a limitaci&amp;oacute;n y una de las pocas que encontraremos, para que todo siga funcionando correctamente, debemos respetar el nombre, en este caso PART_ContentHost. Microsoft recomienda que siempre que tengamos que usar c&amp;oacute;digo contra un objeto parte de una plantilla lo llamemos PART_xxxxxxxx para de esta forma seguir una nomenclatura com&amp;uacute;n.&lt;/div&gt;
&lt;div align="justify"&gt;En este caso los Triggers usados son m&amp;aacute;s sencillos que los del bot&amp;oacute;n, usamos 2 EventTrigger LostFocus y GotFocus y un Trigger a la propiedad IsEnabled:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate.Triggers&amp;gt;
&amp;lt;EventTrigger RoutedEvent=&amp;quot;TextBox.LostFocus&amp;quot;&amp;gt;
&amp;lt;EventTrigger.Actions&amp;gt;
&amp;lt;BeginStoryboard Storyboard=&amp;quot;{StaticResource GlowOut}&amp;quot;&amp;gt;
&amp;lt;/BeginStoryboard&amp;gt;
&amp;lt;/EventTrigger.Actions&amp;gt;
&amp;lt;/EventTrigger&amp;gt;
&amp;lt;EventTrigger RoutedEvent=&amp;quot;TextBox.GotFocus&amp;quot;&amp;gt;
&amp;lt;EventTrigger.Actions&amp;gt;
&amp;lt;BeginStoryboard Storyboard=&amp;quot;{StaticResource GlowIn}&amp;quot;&amp;gt;
&amp;lt;/BeginStoryboard&amp;gt;
&amp;lt;/EventTrigger.Actions&amp;gt;
&amp;lt;/EventTrigger&amp;gt;
&amp;lt;Trigger Property=&amp;quot;IsEnabled&amp;quot; Value=&amp;quot;False&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Opacity&amp;quot; TargetName=&amp;quot;PART_ContentHost&amp;quot; 
Value=&amp;quot;.3&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Opacity&amp;quot; TargetName=&amp;quot;BorderExtern&amp;quot; 
Value=&amp;quot;.5&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Fill&amp;quot; TargetName=&amp;quot;GlassRectangle&amp;quot; 
Value=&amp;quot;{StaticResource GlassFXDisabled}&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;/Trigger&amp;gt;
&amp;lt;/ControlTemplate.Triggers&amp;gt;&lt;/pre&gt;
&lt;h3&gt;Scrollbars&lt;/h3&gt;
&lt;p&gt;El control scrollbar nos va a dar algo m&amp;aacute;s de trabajo que los dos primeros controles, pues involucra partes m&amp;oacute;viles y puede cambiar de orientaci&amp;oacute;n, de vertical a horizontal. &lt;/p&gt;
&lt;div align="center"&gt;&lt;a href="http://lh5.ggpht.com/_7YCdMP8inuc/TApTcOBudoI/AAAAAAAAAD4/7vZ9a2lnZ0A/s1600-h/Scrollbars%5B3%5D.png"&gt;&lt;img height="200" width="155" src="http://lh3.ggpht.com/_7YCdMP8inuc/TApTc4qJXsI/AAAAAAAAAD8/HsoZD1h9plk/Scrollbars_thumb%5B1%5D.png?imgmax=800" alt="Scrollbars" border="0" title="Scrollbars" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;Para este control Debemos definir varios estilos por separado y controltemplates independientes, uno para la barra vertical y otro para la barra horizontal.&lt;/div&gt;
&lt;p&gt;Primero empezaremos definiendo los estilos de los controles que componen un scrollbar, LineButtons, PageButtons y ScrollThumb: &lt;/p&gt;
&lt;div align="center"&gt;&lt;a href="http://lh4.ggpht.com/_7YCdMP8inuc/TApTdtrnEuI/AAAAAAAAAEA/aYPp311LewI/s1600-h/scrollbar_parts%5B4%5D.png"&gt;&lt;img height="143" width="187" src="http://lh5.ggpht.com/_7YCdMP8inuc/TApTeeNlTcI/AAAAAAAAAEE/09bfc5oBOqs/scrollbar_parts_thumb%5B2%5D.png?imgmax=800" alt="scrollbar_parts" border="0" title="scrollbar_parts" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;h5&gt;&lt;/h5&gt;
&lt;h5&gt;LineButton:&lt;/h5&gt;
&lt;div align="justify"&gt;Los LineButtons son los botones en los extremos del scrollbar, el tipo de control es repeatbutton y su controltemplate es muy sencillo:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate x:Name=&amp;quot;tmplRepeatButton&amp;quot;&amp;gt;
&amp;lt;Border Background=&amp;quot;#FF222222&amp;quot; BorderBrush=&amp;quot;DarkBlue&amp;quot; 
BorderThickness=&amp;quot;1&amp;quot; CornerRadius=&amp;quot;3&amp;quot;&amp;gt;
&amp;lt;Path HorizontalAlignment=&amp;quot;Center&amp;quot; 
VerticalAlignment=&amp;quot;Center&amp;quot; 
Data=&amp;quot;{Binding Path=Content,
RelativeSource={RelativeSource TemplatedParent}}&amp;quot; 
Fill=&amp;quot;Cyan&amp;quot; &amp;gt;
&amp;lt;/Path&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Se compone solo de dos controles, un Border que define el aspecto del control, y contiene un objeto Path, cuya propiedad Data asociamos a la propiedad Content del control al que a&amp;ntilde;adiremos esta plantilla. La gran potencia del objeto Path viene dada por su propiedad Data, pues dispone de un &amp;ldquo;mini lenguaje&amp;rdquo; para especificar geometr&amp;iacute;as complejas de una forma r&amp;aacute;pida y sencilla. Pod&amp;eacute;is encontrar una referencia muy completa en msdn &lt;a target="_blank" rel="nofollow" href="http://msdn.microsoft.com/en-us/library/ms752293.aspx"&gt;aqu&amp;iacute;.&lt;/a&gt;&lt;/div&gt;
&lt;div align="justify"&gt;Su nombre viene indicado por la acci&amp;oacute;n que realiza, pues cada vez que se pulsa un LineButton se avanza o retrocede una linea del control que estemos usando.&lt;/div&gt;
&lt;h5&gt;PageButtons:&lt;/h5&gt;
&lt;div align="justify"&gt;Los page buttons act&amp;uacute;an como el fondo de la barra sobre la que desplazamos el scrollbar, como su nombre indica son los encargados de mover adelante o atr&amp;aacute;s una p&amp;aacute;gina completa, el tipo de control es tambi&amp;eacute;n repeatbutton.&lt;/div&gt;
&lt;div align="justify"&gt;Su control template es muy sencillo y se compone de un solo objeto Border:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate x:Name=&amp;quot;tmplRepeatButton&amp;quot;&amp;gt;
&amp;lt;Border Background=&amp;quot;#66000000&amp;quot; BorderBrush=&amp;quot;Black&amp;quot; 
BorderThickness=&amp;quot;1&amp;quot; CornerRadius=&amp;quot;3&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Como pod&amp;eacute;is ver, tanto el template del LineButton como el del PageButton tienen el mismo nombre, esto se debe a que al ser plantillas incrustadas dentro de un estilo, su &amp;aacute;mbito es el estilo y no colisionan entre s&amp;iacute;.&lt;/div&gt;
&lt;h5&gt;ScrollThumb:&lt;/h5&gt;
&lt;div align="justify"&gt;El scrollthumb es la parte m&amp;oacute;vil del scrollbar, se redimensiona a medida que es necesario m&amp;aacute;s scroll o menos y podemos pincharlo y arrastrarlo para movernos por el contenido, el tipo de control usado es Thumb, puesto que incluye funcionalidad para Drag&amp;amp;Drop de forma nativa, su control template tambi&amp;eacute;n es algo m&amp;aacute;s complejo que los anteriores botones:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate x:Name=&amp;quot;tmplScrollThumb&amp;quot;&amp;gt;
&amp;lt;Grid&amp;gt;
&amp;lt;Rectangle RadiusX=&amp;quot;3&amp;quot; RadiusY=&amp;quot;3&amp;quot; Fill=&amp;quot;#66222222&amp;quot;&amp;gt;
&amp;lt;/Rectangle&amp;gt;
&amp;lt;Border CornerRadius=&amp;quot;3&amp;quot; BorderBrush=&amp;quot;DarkBlue&amp;quot; 
Background=&amp;quot;{StaticResource GlassFX}&amp;quot;&amp;gt;
&amp;lt;Path HorizontalAlignment=&amp;quot;Center&amp;quot; 
VerticalAlignment=&amp;quot;Center&amp;quot; 
Data=&amp;quot;{Binding Path=Content,
RelativeSource={RelativeSource TemplatedParent}}&amp;quot;&amp;gt;
&amp;lt;/Path&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;/Grid&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Tenemos una grid que contendr&amp;aacute; nuestros controles, un rect&amp;aacute;ngulo que act&amp;uacute;a como fondo base del Thumb. un Border para darle el efecto de cristal y dentro de este un objeto Path para que podamos incluir una geometr&amp;iacute;a personalizada si lo deseamos.&lt;/div&gt;
&lt;div align="justify"&gt;&lt;/div&gt;
&lt;div align="justify"&gt;Ahora que ya hemos definido las plantillas y estilos de nuestros controles base, podemos pasar a definir las plantillas de las Scrollbar tanto vertical como Horizontal:&lt;/div&gt;
&lt;h5&gt;Scrollbar vertical:&lt;/h5&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate x:Key=&amp;quot;VerticalScroll&amp;quot; TargetType=&amp;quot;{x:Type ScrollBar}&amp;quot;&amp;gt;
&amp;lt;Grid&amp;gt;
&amp;lt;Grid.RowDefinitions&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;18&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;0.00001*&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;RowDefinition Height=&amp;quot;18&amp;quot;&amp;gt;&amp;lt;/RowDefinition&amp;gt;
&amp;lt;/Grid.RowDefinitions&amp;gt;
&amp;lt;Border Grid.RowSpan=&amp;quot;3&amp;quot; CornerRadius=&amp;quot;3&amp;quot; 
BorderBrush=&amp;quot;DarkBlue&amp;quot; BorderThickness=&amp;quot;1&amp;quot; 
Opacity=&amp;quot;.6&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;RepeatButton Grid.Row=&amp;quot;0&amp;quot; 
Style=&amp;quot;{StaticResource LineButton}&amp;quot; 
Height=&amp;quot;18&amp;quot; Command=&amp;quot;ScrollBar.LineUpCommand&amp;quot; 
Content=&amp;quot;M 0 4 L 8 4 L 4 0 Z&amp;quot;&amp;gt;
&amp;lt;/RepeatButton&amp;gt;
&amp;lt;Track Name=&amp;quot;PART_Track&amp;quot; Grid.Row=&amp;quot;1&amp;quot; IsDirectionReversed=&amp;quot;True&amp;quot;&amp;gt;
&amp;lt;Track.DecreaseRepeatButton&amp;gt;
&amp;lt;RepeatButton Style=&amp;quot;{StaticResource PageButton}&amp;quot; 
Command=&amp;quot;ScrollBar.PageUpCommand&amp;quot; /&amp;gt;
&amp;lt;/Track.DecreaseRepeatButton&amp;gt;
&amp;lt;Track.Thumb&amp;gt;
&amp;lt;Thumb Style=&amp;quot;{StaticResource ScrollThumb}&amp;quot; /&amp;gt;
&amp;lt;/Track.Thumb&amp;gt;
&amp;lt;Track.IncreaseRepeatButton&amp;gt;
&amp;lt;RepeatButton Style=&amp;quot;{StaticResource PageButton}&amp;quot; 
Command=&amp;quot;ScrollBar.PageDownCommand&amp;quot; /&amp;gt;
&amp;lt;/Track.IncreaseRepeatButton&amp;gt;
&amp;lt;/Track&amp;gt;
&amp;lt;RepeatButton Grid.Row=&amp;quot;2&amp;quot; 
Style=&amp;quot;{StaticResource LineButton}&amp;quot; 
Height=&amp;quot;18&amp;quot; Command=&amp;quot;ScrollBar.LineDownCommand&amp;quot; 
Content=&amp;quot;M 0 0 L 4 4 L 8 0 Z&amp;quot;&amp;gt;
&amp;lt;/RepeatButton&amp;gt;            
&amp;lt;/Grid&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Este ya es un control template m&amp;aacute;s complejo, compuesto de m&amp;aacute;s controles. Para empezar tenemos una grid a la que le definimos 3 Rows, la primera y la ultima contendr&amp;aacute;n los botones de subir y bajar usando repeatbuttons a los que les aplicamos el estilo que anteriormente creamos LineButton.&lt;/div&gt;
&lt;div align="justify"&gt;En la parte central de la grid definimos un objeto Track, puesto que esta parte de un scrollbar tiene c&amp;oacute;digo asociado le asignamos el mismo nombre que el del original: PART_Track y dentro del mismo tenemos 3 propiedades que debemos rellenar: DecreaseRepeatButton, Thumb e IncreaseRepeatButton. En el DecreaseRepeatButton e IncreaseRepeatButton definimos RepeatButtons con el estilo PageButton que creamos anteriormente y en Thumb definimos un control Thumb con el estilo ScrollThumb.&lt;/div&gt;
&lt;div align="justify"&gt;Algo a tener en cuenta es el Content de los RepeatButton usados con el estilo LineButton, estas combinaciones de letras y n&amp;uacute;meros son el &amp;ldquo;mini lenguaje&amp;rdquo; de geometr&amp;iacute;a que usa el objeto Path para dibujar formas, es muy &amp;uacute;til e interesante, en el apartado del estilo LineButton ten&amp;eacute;is un enlace a una descripci&amp;oacute;n completa de este lenguaje.&lt;/div&gt;
&lt;h5&gt;Scrollbar Horizontal:&lt;/h5&gt;
&lt;div align="justify"&gt;El scrollbar horizontal es id&amp;eacute;ntico al scrollbar vertical, solo que en vez de dividir la Grid en Rows la dividimos en Columnas, usando la primera y ultima columna para los LineButtons y la columna central para el Track:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate x:Key=&amp;quot;HorizontalScroll&amp;quot; TargetType=&amp;quot;{x:Type ScrollBar}&amp;quot;&amp;gt;
&amp;lt;Grid&amp;gt;
&amp;lt;Grid.ColumnDefinitions&amp;gt;
&amp;lt;ColumnDefinition Width=&amp;quot;18&amp;quot;&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
&amp;lt;ColumnDefinition Width=&amp;quot;0.00001*&amp;quot;&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
&amp;lt;ColumnDefinition Width=&amp;quot;18&amp;quot;&amp;gt;&amp;lt;/ColumnDefinition&amp;gt;
&amp;lt;/Grid.ColumnDefinitions&amp;gt;
&amp;lt;Border Grid.ColumnSpan=&amp;quot;3&amp;quot; CornerRadius=&amp;quot;3&amp;quot; 
BorderBrush=&amp;quot;DarkBlue&amp;quot; BorderThickness=&amp;quot;1&amp;quot; 
Opacity=&amp;quot;.6&amp;quot; &amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;RepeatButton Grid.Column=&amp;quot;0&amp;quot; 
Style=&amp;quot;{StaticResource LineButton}&amp;quot; 
Width=&amp;quot;18&amp;quot; Command=&amp;quot;ScrollBar.LineLeftCommand&amp;quot; 
Content=&amp;quot;M 4 0 L 4 8 L 0 4 Z&amp;quot;&amp;gt;
&amp;lt;/RepeatButton&amp;gt;
&amp;lt;Track Name=&amp;quot;PART_Track&amp;quot; Grid.Column=&amp;quot;1&amp;quot; IsDirectionReversed=&amp;quot;False&amp;quot;&amp;gt;
&amp;lt;Track.DecreaseRepeatButton&amp;gt;
&amp;lt;RepeatButton Style=&amp;quot;{StaticResource PageButton}&amp;quot; 
Command=&amp;quot;ScrollBar.PageLeftCommand&amp;quot; /&amp;gt;
&amp;lt;/Track.DecreaseRepeatButton&amp;gt;
&amp;lt;Track.Thumb&amp;gt;
&amp;lt;Thumb Style=&amp;quot;{StaticResource ScrollThumb}&amp;quot; /&amp;gt;
&amp;lt;/Track.Thumb&amp;gt;
&amp;lt;Track.IncreaseRepeatButton&amp;gt;
&amp;lt;RepeatButton Style=&amp;quot;{StaticResource PageButton}&amp;quot; 
Command=&amp;quot;ScrollBar.PageRightCommand&amp;quot; /&amp;gt;
&amp;lt;/Track.IncreaseRepeatButton&amp;gt;
&amp;lt;/Track&amp;gt;
&amp;lt;RepeatButton Grid.Column=&amp;quot;2&amp;quot; 
Style=&amp;quot;{StaticResource LineButton}&amp;quot;
Width=&amp;quot;18&amp;quot; Command=&amp;quot;ScrollBar.LineRightCommand&amp;quot;
Content=&amp;quot;M 0 0 L 4 4 L 0 8 Z&amp;quot;&amp;gt;
&amp;lt;/RepeatButton&amp;gt;
&amp;lt;/Grid&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Por &amp;uacute;ltimo solo nos queda definir un estilo com&amp;uacute;n para el control Scrollbar que decida que plantilla aplicar dependiendo de la orientaci&amp;oacute;n designada por el control:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Style TargetType=&amp;quot;{x:Type ScrollBar}&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;OverridesDefaultStyle&amp;quot; Value=&amp;quot;True&amp;quot; /&amp;gt;
&amp;lt;Setter Property=&amp;quot;SnapsToDevicePixels&amp;quot; Value=&amp;quot;True&amp;quot; /&amp;gt;
&amp;lt;Style.Triggers&amp;gt;
&amp;lt;Trigger Property=&amp;quot;Orientation&amp;quot; Value=&amp;quot;Vertical&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Width&amp;quot; Value=&amp;quot;18&amp;quot;&amp;gt;&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Height&amp;quot; Value=&amp;quot;Auto&amp;quot;&amp;gt;&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Template&amp;quot; Value=&amp;quot;{StaticResource VerticalScroll}&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;/Trigger&amp;gt;
&amp;lt;Trigger Property=&amp;quot;Orientation&amp;quot; Value=&amp;quot;Horizontal&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Width&amp;quot; Value=&amp;quot;Auto&amp;quot;&amp;gt;&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Height&amp;quot; Value=&amp;quot;18&amp;quot;&amp;gt;&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Template&amp;quot; Value=&amp;quot;{StaticResource HorizontalScroll}&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;/Trigger&amp;gt;            
&amp;lt;/Style.Triggers&amp;gt;
&amp;lt;/Style&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Este es un estilo sencillo, simplemente tenemos dos Triggers que controlan la propiedad Orientation, y dependiendo de su valor aplican una plantilla u otra.&lt;/div&gt;
&lt;h3&gt;ProgressBar&lt;/h3&gt;
&lt;div align="justify"&gt;La barra de progreso es un control muy &amp;uacute;til para ofrecer informaci&amp;oacute;n al usuario a cerca de la realizaci&amp;oacute;n de una tarea que se alarga en el tiempo un poco. En este caso a parte de darle una apariencia m&amp;aacute;s atractiva tambi&amp;eacute;n vamos a darle un toque m&amp;aacute;s de funcionalidad, permitiendo indicar al usuario el porcentaje del trabajo realizado de forma num&amp;eacute;rica. Tambi&amp;eacute;n tenemos soporte para trabajos con duraci&amp;oacute;n indeterminada:&lt;/div&gt;
&lt;div align="center"&gt;&lt;a href="http://lh3.ggpht.com/_7YCdMP8inuc/TApTe0PB1sI/AAAAAAAAAEI/i1RAEPzIIuM/s1600-h/progressbar%5B3%5D.png"&gt;&lt;img height="180" width="203" src="http://lh6.ggpht.com/_7YCdMP8inuc/TApTflN9PKI/AAAAAAAAAEM/-QFoOtqkkPk/progressbar_thumb%5B1%5D.png?imgmax=800" alt="progressbar" border="0" title="progressbar" style="border-bottom-width:0px;border-left-width:0px;border-right-width:0px;border-top-width:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;En la imagen superior podemos ver 3 estados de una ProgressBar: Determinado, Indeterminado y Desactivado. Como pod&amp;eacute;is ver en los estados Determinado y desactivado se ofrece una informaci&amp;oacute;n visual del % realizado en forma de n&amp;uacute;mero.&lt;/div&gt;
&lt;p&gt;El Control template es muy parecido al de cualquier otro control que hayamos visto: &lt;/p&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate TargetType=&amp;quot;{x:Type ProgressBar}&amp;quot;&amp;gt;
&amp;lt;Grid MinHeight=&amp;quot;14&amp;quot; MinWidth=&amp;quot;20&amp;quot;&amp;gt;
&amp;lt;Border x:Name=&amp;quot;BaseRectangle&amp;quot; 
Background=&amp;quot;{StaticResource BaseColor}&amp;quot; 
CornerRadius=&amp;quot;10,0,10,0&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;GlassRectangle&amp;quot; CornerRadius=&amp;quot;10,0,10,0&amp;quot;  
Background=&amp;quot;{StaticResource GlassFX}&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;animation&amp;quot; CornerRadius=&amp;quot;10,0,10,0&amp;quot; 
Opacity=&amp;quot;.7&amp;quot; Background=&amp;quot;{StaticResource GlowFXProgress}&amp;quot; 
HorizontalAlignment=&amp;quot;Left&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;PART_Indicator&amp;quot; CornerRadius=&amp;quot;10,0,10,0&amp;quot; 
Background=&amp;quot;{StaticResource GlowFXProgress}&amp;quot; 
HorizontalAlignment=&amp;quot;Left&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;PART_Track&amp;quot; BorderThickness=&amp;quot;1&amp;quot; 
CornerRadius=&amp;quot;10,0,10,0&amp;quot; BorderBrush=&amp;quot;Black&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Border x:Name=&amp;quot;BordeCabeceraSombra&amp;quot; BorderThickness=&amp;quot;2&amp;quot; 
CornerRadius=&amp;quot;10,0,10,0&amp;quot; BorderBrush=&amp;quot;DarkGray&amp;quot; 
Opacity=&amp;quot;.2&amp;quot; Margin=&amp;quot;1,1,1,0&amp;quot;&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;Label x:Name=&amp;quot;Progress&amp;quot; VerticalAlignment=&amp;quot;Stretch&amp;quot; 
HorizontalAlignment=&amp;quot;Stretch&amp;quot; 
HorizontalContentAlignment=&amp;quot;Center&amp;quot; 
VerticalContentAlignment=&amp;quot;Center&amp;quot; 
FontWeight=&amp;quot;Bold&amp;quot; Foreground=&amp;quot;White&amp;quot; Opacity=&amp;quot;.7&amp;quot; 
Content=&amp;quot;{Binding Path=Value, 
RelativeSource={RelativeSource TemplatedParent}}&amp;quot;&amp;gt;
&amp;lt;/Label&amp;gt;
&amp;lt;/Grid&amp;gt;
&amp;lt;ControlTemplate.Triggers&amp;gt;
&amp;lt;Trigger Property=&amp;quot;IsIndeterminate&amp;quot; Value=&amp;quot;True&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Visibility&amp;quot; TargetName=&amp;quot;Progress&amp;quot; Value=&amp;quot;Hidden&amp;quot;&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Background&amp;quot; TargetName=&amp;quot;PART_Indicator&amp;quot;&amp;gt;
&amp;lt;Setter.Value&amp;gt;
&amp;lt;MultiBinding&amp;gt;
&amp;lt;MultiBinding.Converter&amp;gt;
&amp;lt;wintheme:ProgressBarHighlightConverter/&amp;gt;
&amp;lt;/MultiBinding.Converter&amp;gt;
&amp;lt;Binding Source=&amp;quot;{StaticResource GlowFXProgressAnimated}&amp;quot;/&amp;gt;
&amp;lt;Binding Path=&amp;quot;ActualWidth&amp;quot;  ElementName=&amp;quot;BaseRectangle&amp;quot;/&amp;gt;
&amp;lt;Binding Path=&amp;quot;ActualHeight&amp;quot; ElementName=&amp;quot;BaseRectangle&amp;quot;/&amp;gt;
&amp;lt;/MultiBinding&amp;gt;
&amp;lt;/Setter.Value&amp;gt;
&amp;lt;/Setter&amp;gt;
&amp;lt;/Trigger&amp;gt;
&amp;lt;Trigger Property=&amp;quot;IsEnabled&amp;quot; Value=&amp;quot;False&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Opacity&amp;quot; Value=&amp;quot;.5&amp;quot;&amp;gt;&amp;lt;/Setter&amp;gt;
&amp;lt;/Trigger&amp;gt;
&amp;lt;/ControlTemplate.Triggers&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Esta plantilla es larga pero no es complicada, lo m&amp;aacute;s interesante de la misma se encuentra en dos puntos, primero, el control label que compone la plantilla, cuyo contenido est&amp;aacute; enlazado a la propiedad Value de la progressbar, de esta forma siempre que cambie la propiedad value se reflejar&amp;aacute; en el control label.&lt;/div&gt;
&lt;div align="justify"&gt;El segundo se encuentra en el Trigger que controla cuando la propiedad IsIndeterminate es verdadera, cambiamos el valor de la propiedad background del control PART_Indicator usando un Multibinding Converter, esto es una clase que acepta varios valores de entrada y devuelve un valor de salida. En nuestro caso queremos conservar la funcionalidad de Windows Vista y 7 en las barras indeterminadas, para ello debemos incluir en nuestro proyecto una referencia al ensamblado: &lt;strong&gt;PressentationFramework.Aero&lt;/strong&gt; y referenciarlo en el archivo xaml de nuestro tema de la siguiente forma:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;xmlns:wintheme=&amp;quot;clr-namespace:Microsoft.Windows.Themes;
assembly=PresentationFramework.Aero&amp;quot;&lt;/pre&gt;
&lt;p&gt;Con esto nuestra progressbar funcionar&amp;aacute; perfectamente. &lt;/p&gt;
&lt;h3&gt;Conclusi&amp;oacute;n&lt;/h3&gt;
&lt;p&gt;El tema Black Crystal incluye otros controles como son Datagrid, TabControl y GroupBox. Os dejo como tarea para casa el analizarlos, con lo visto aqu&amp;iacute; ver&amp;eacute;is que no es complicado comprenderlos. Un gran saludo y Happy Coding!&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;iframe scrolling="no" marginwidth="0" frameborder="0" src="http://cid-fd100135b82f3364.skydrive.live.com/embedicon.aspx/.Public/ejemplos/NET%204%20WPF%20Estilos" marginheight="0" title="Preview" style="background-color:#fcfcfc;width:98px;height:115px;visibility:hidden;padding:0px;"&gt;&lt;/iframe&gt;&lt;/p&gt;</description></item><item><title>WPF: Personalizar nuestra aplicación con Styles y Control Templates (I)</title><link>http://geeks.ms/wikis/wpf/wpf-personalizar-nuestra-aplicaci-243-n-con-styles-y-control-templates-i/revision/0.aspx</link><pubDate>Mon, 26 Jul 2010 04:31:19 GMT</pubDate><guid isPermaLink="false">2a2e7ade-7474-448b-9de5-1515d8bb7d1b:7</guid><dc:creator>Josué Yeray Julián Ferreiro</dc:creator><description>Revisión actual enviado a Wiki sobre WPF en Geeks•ms por Josué Yeray Julián Ferreiro a 7/26/2010 6:31:19 AM&lt;br /&gt;
&lt;div align="justify"&gt;Hist&amp;oacute;ricamente, desde los tiempos de Visual Basic a Windows Forms, si dese&amp;aacute;bamos crear una interface personalizada para nuestra aplicaci&amp;oacute;n est&amp;aacute;bamos, limitados a cambiar ciertas propiedades est&amp;aacute;ndar de los controles como el color de fondo, ancho del borde o el tama&amp;ntilde;o de fuente. Si dese&amp;aacute;bamos ir m&amp;aacute;s all&amp;aacute;, nuestra &amp;uacute;nica opci&amp;oacute;n es crear un nuevo control, heredar desde el control existente e invalidar el m&amp;eacute;todo de dibujado para implementar nuestra propia l&amp;oacute;gica de dibujo.&lt;/div&gt;
&lt;div align="justify"&gt;Esto sigue siendo posible en WPF, pero ya no es necesario, pues WPF nos facilita un modelo de extensibilidad basado en Plantillas y Estilos, que nos permite realizar complejas modificaciones y redefiniciones del aspecto visual de un control, sin tener que crear uno nuevo.&lt;/div&gt;
&lt;div align="justify"&gt;&lt;/div&gt;
&lt;!--more--&gt;
&lt;div align="justify"&gt;&lt;/div&gt;
&lt;h3&gt;Nuestro trabajo&lt;/h3&gt;
&lt;div align="justify"&gt;A continuaci&amp;oacute;n puedes ver el origen desde el que vamos a partir:&lt;/div&gt;
&lt;div align="center"&gt;&lt;a href="http://lh4.ggpht.com/_7YCdMP8inuc/TAJ6KSlYyFI/AAAAAAAAADQ/-ct8olcNosA/s1600-h/sin%20estilos%5B4%5D.png"&gt;&lt;img height="450" width="640" src="http://lh3.ggpht.com/_7YCdMP8inuc/TAJ6PSyPPLI/AAAAAAAAADU/cBSUG7BzVhE/sin%20estilos_thumb%5B2%5D.png?imgmax=800" alt="sin estilos" border="0" title="sin estilos" style="border-bottom:0px;border-left:0px;border-right:0px;border-top:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;Y nuestro objetivo es llegar a lo siguiente:&lt;/div&gt;
&lt;div align="center"&gt;&lt;a href="http://lh4.ggpht.com/_7YCdMP8inuc/TAJ6VKWBPPI/AAAAAAAAADY/IWxp5iI-Bs8/s1600-h/Apariencia%5B4%5D.png"&gt;&lt;img height="448" width="640" src="http://lh4.ggpht.com/_7YCdMP8inuc/TAJ6bD5JjlI/AAAAAAAAADc/sF8TolwkG0A/Apariencia_thumb%5B2%5D.png?imgmax=800" alt="Apariencia" border="0" title="Apariencia" style="border-bottom:0px;border-left:0px;border-right:0px;border-top:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;Como puedes ver el cambio es muy grande, es mucho mas atractivo a la vista, con lo que nuestros usuarios se sentir&amp;aacute;n m&amp;aacute;s c&amp;oacute;modos y nuestra aplicaci&amp;oacute;n ganar&amp;aacute; una apariencia exclusiva y &amp;uacute;nica. As&amp;iacute; que, manos a la obra, pero primero, vamos a repasar algunos conceptos b&amp;aacute;sicos de Styles y ControlTemplates en WPF.&lt;/div&gt;
&lt;h3&gt;Un poco de teor&amp;iacute;a&lt;/h3&gt;
&lt;div align="justify"&gt;WPF nos brinda varias formas de personalizar nuestros controles:&amp;nbsp;&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;Contenido Enriquecido&lt;/li&gt;
&lt;li&gt;Styles&lt;/li&gt;
&lt;li&gt;Data Templates&lt;/li&gt;
&lt;li&gt;Control Templates&lt;/li&gt;
&lt;/ul&gt;
&lt;div align="justify"&gt;En este post me voy a centrar en los Styles y los Control Templates.&lt;/div&gt;
&lt;h5&gt;Styles&lt;/h5&gt;
&lt;div align="justify"&gt;Un objeto Style es una colecci&amp;oacute;n de valores que representan propiedades para el control indicado. Podemos asignarle autom&amp;aacute;ticamente a todos los controles de un mismo tipo, por ejemplo un Button, ciertas propiedades como el color de fondo, tipo de letra, etc&amp;hellip; de esta forma todos nuestros controles de este tipo obtendr&amp;aacute;n estas caracter&amp;iacute;sticas: &lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Style TargetType=&amp;quot;{x:Type Button}&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Background&amp;quot; Value=&amp;quot;Red&amp;quot;&amp;gt;&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Foreground&amp;quot; Value=&amp;quot;White&amp;quot;&amp;gt;&amp;lt;/Setter&amp;gt;
&amp;lt;/Style&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Tambi&amp;eacute;n podemos establecer un nombre al estilo y aplicarlo manualmente a los controles que nos interese usando la propiedad Style de cada uno:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Style x:Key=&amp;quot;EstiloPropio&amp;quot; TargetType=&amp;quot;{x:Type Button}&amp;quot;&amp;gt;
&amp;lt;Setter Property=&amp;quot;Background&amp;quot; Value=&amp;quot;Red&amp;quot;&amp;gt;&amp;lt;/Setter&amp;gt;
&amp;lt;Setter Property=&amp;quot;Foreground&amp;quot; Value=&amp;quot;White&amp;quot;&amp;gt;&amp;lt;/Setter&amp;gt;
&amp;lt;/Style&amp;gt;

&amp;lt;Button Style=&amp;quot;{StaticResource EstiloPropio}&amp;quot;&amp;gt;&amp;lt;/Button&amp;gt;&lt;/pre&gt;
&lt;h5&gt;Control Templates&lt;/h5&gt;
&lt;div align="justify"&gt;Muchos controles en WPF utilizan plantillas para definir su estructura y apariencia. De esta forma su funcionalidad permanece intacta aunque cambiemos su apariencia, y nos da un grado de personalizaci&amp;oacute;n sobre el aspecto del control sin precedentes. Esto nos permite elegir un control por su funcionalidad para llevar a cabo una tarea, sin tener en cuenta que su apariencia no se ajuste a lo que deseamos, pues esta puede ser redefinida totalmente. Este es un ejemplo sencillo de un ControlTemplate para un bot&amp;oacute;n:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ControlTemplate TargetType=&amp;quot;{x:Type Button}&amp;quot;&amp;gt;
&amp;lt;Border Name=&amp;quot;fondoboton&amp;quot; BorderBrush=&amp;quot;red&amp;quot; BorderThickness=&amp;quot;5&amp;quot; 
Background=&amp;quot;Yellow&amp;quot;&amp;gt;
&amp;lt;ContentPresenter Name=&amp;quot;contenido&amp;quot; 
Content=&amp;quot;{Binding Path=Content, 
RelativeSource={RelativeSource TemplatedParent}}&amp;quot;&amp;gt;
&amp;lt;/ContentPresenter&amp;gt;
&amp;lt;/Border&amp;gt;
&amp;lt;/ControlTemplate&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Y el resultado de esta plantilla si ponemos un bot&amp;oacute;n en nuestro proyecto ser&amp;iacute;a este:&lt;/div&gt;
&lt;div align="center"&gt;&lt;a href="http://lh4.ggpht.com/_7YCdMP8inuc/TAJ6b1MulrI/AAAAAAAAADg/MmfavknlVXY/s1600-h/boton%5B3%5D.png"&gt;&lt;img height="40" width="140" src="http://lh6.ggpht.com/_7YCdMP8inuc/TAJ6cscVlpI/AAAAAAAAADk/0fzF6dV723I/boton_thumb%5B1%5D.png?imgmax=800" alt="boton" border="0" title="boton" style="border-bottom:0px;border-left:0px;border-right:0px;border-top:0px;display:inline;" /&gt;&lt;/a&gt; &lt;/div&gt;
&lt;div align="justify"&gt;Como puedes ver, el control a perdido todo su aspecto, que ha sido reemplazado por el que hemos indicado, pero conservando todo su comportamiento y funcionalidad de bot&amp;oacute;n.&lt;/div&gt;
&lt;h3&gt;Definir el estilo de nuestra aplicaci&amp;oacute;n&lt;/h3&gt;
&lt;div align="justify"&gt;Un paso muy importante a la hora de definir el estilo de nuestra aplicaci&amp;oacute;n es que esta mantenga una coherencia visual a trav&amp;eacute;s de las diferentes pantallas de la misma, para que el usuario tenga una sensaci&amp;oacute;n de familiaridad con nuestra aplicaci&amp;oacute;n aunque se enfrente a pantallas nuevas.&lt;/div&gt;
&lt;div align="justify"&gt;Otro aspecto muy importante es la sencillez de implantaci&amp;oacute;n, en una aplicaci&amp;oacute;n con cientos de controles y decenas de pantallas, no podemos ir control por control y pantalla por pantalla ajustando par&amp;aacute;metros visuales, debe realizarse de forma autom&amp;aacute;tica, para esto WPF nos facilita los ResourceDictionary, archivos Xaml donde podemos incluir todo nuestro c&amp;oacute;digo de estilado e incluirlos de forma global en toda la aplicaci&amp;oacute;n, con lo que, cualquier cambio que hagamos en el estilo o plantilla de un control se aplicar&amp;aacute; autom&amp;aacute;ticamente a todos lo controles de nuestra aplicaci&amp;oacute;n.&lt;/div&gt;
&lt;div align="justify"&gt;Lo primero que debemos realizar es a&amp;ntilde;adir en nuestra aplicaci&amp;oacute;n un nuevo elemento de tipo ResourceDictionary, en mi caso el nombre es BlackCrystal.xaml, este archivo solo tiene vista xaml y al incluirlo deber&amp;iacute;a aparecer algo as&amp;iacute;:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;ResourceDictionary xmlns=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;
xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;&amp;gt;


&amp;lt;/ResourceDictionary&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Una vez que tengamos nuestro ResourceDictionary agregado, es momento de indicarle a nuestra aplicaci&amp;oacute;n que haga uso de el, esto lo podemos hacer editando el archivo Application.xaml para decirle la ruta de un nuevo diccionario de recursos que queremos que use, deber&amp;iacute;a quedar as&amp;iacute;:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Application x:Class=&amp;quot;Application&amp;quot;
xmlns=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml/presentation&amp;quot;
xmlns:x=&amp;quot;http://schemas.microsoft.com/winfx/2006/xaml&amp;quot;
StartupUri=&amp;quot;MainWindow.xaml&amp;quot;&amp;gt;
&amp;lt;Application.Resources&amp;gt;
&amp;lt;ResourceDictionary Source=&amp;quot;BlackCrystal.xaml&amp;quot;&amp;gt;&amp;lt;/ResourceDictionary&amp;gt;
&amp;lt;/Application.Resources&amp;gt;
&amp;lt;/Application&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Simplemente a&amp;ntilde;adimos un nuevo nodo Application.Resources y dentro del mismo creamos un nuevo objeto ResourceDictionary, indic&amp;aacute;ndole la Ruta (Source) desde la que cargar este diccionario. Con esto, cualquier estilo o plantilla que creemos en nuestro ResourceDictionary estar&amp;aacute; inmediatamente disponible en toda nuestra aplicaci&amp;oacute;n.&lt;/div&gt;
&lt;h3&gt;Elementos Comunes&lt;/h3&gt;
&lt;div align="justify"&gt;Algo importante a la hora de dise&amp;ntilde;ar el look &amp;amp; feel de nuestra aplicaci&amp;oacute;n es dotarla con una apariencia uniforme, mismos colores, mismas geometr&amp;iacute;as y mismas animaciones, si defini&amp;eacute;semos directamente estos par&amp;aacute;metros en cada uno de los estilos y plantillas convertir&amp;iacute;a el mantenimiento de los mismos en un infierno, teniendo que recorrer decenas de sitios para cambiar un solo color. Para solucionar esto el primer trabajo que debemos hacer es definir en nuestro resource dictionary todos los colores y animaciones que queramos usar.El tema de ejemplo que he creado, Black Crystal, usa en total 9 degradados distintos y 2 animaciones que se aplican a todos los controles, estos degradados son de tipo LinearGradient y RadialGradient y las animaciones son DoubleAnimations.&lt;/div&gt;
&lt;div align="justify"&gt;Aqu&amp;iacute; pod&amp;eacute;is ver un ejemplo de Degradado Lineal, este es usado para aplicar al fondo de las ventanas un degradado en tonos de grises:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;LinearGradientBrush x:Key=&amp;quot;DarkBackground&amp;quot; StartPoint=&amp;quot;0,0&amp;quot; EndPoint=&amp;quot;1,1&amp;quot;&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;0&amp;quot; Color=&amp;quot;#FF333344&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;1&amp;quot; Color=&amp;quot;#FF666677&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;/LinearGradientBrush&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;El c&amp;oacute;digo xaml es muy sencillo, en la primera l&amp;iacute;nea definimos el tipo de objeto (LinearGradientBrush) le asignamos una Key para poder usar el recurso que estamos creando desde cualquier parte e indicamos el Punto de inicio y de Final, estos puntos se especifican con una pareja de n&amp;uacute;meros que van de 0 a 1, indicando 0,0 la esquina superior izquierda y 1,1 la esquina inferior derecha, el primer numero de cada par indica el punto en el eje X y el segundo n&amp;uacute;mero indica el punto en el eje Y. de esta forma 0,0 a 1,1 indica que nuestro degradado recorrer&amp;aacute; la diagonal desde la esquina superior izquierda a la esquina inferior derecha, un valor de 0,0 a 1,0 indicar&amp;iacute;a que nuestro degradado empezar&amp;iacute;a en la esquina superior izquierda y acabar&amp;iacute;a en la esquina superior derecha, con lo que tendr&amp;iacute;amos un aspecto de degradado de izquierda a derecha horizontal, un valor de 0,0 a 0,1 crear&amp;iacute;a un efecto de degradado vertical.&lt;/div&gt;
&lt;div align="justify"&gt;Los objetos gradientStop indican que color se usara en cada parte del degradado, un degradado puede tener tantos GradientStop como queramos, la propiedad Offset indica la posici&amp;oacute;n del color dentro del degradado, siendo 0 el inicio y 1 el final, podemos usar cualquier valor entre estos n&amp;uacute;meros tal como .2, .35 o .98 y por ultimo Color indica el color a usar en ese punto del degradado, puede ser un color ya establecido por el sistema como White, Purple o Black o una combinaci&amp;oacute;n de colores ARGB (A = Alpha (transparencia), R = Rojo, G = Verde y B = Azul)&lt;/div&gt;
&lt;div align="justify"&gt;El Objeto RadialGradientBrush es muy parecido al LinearGradientBrush y se compone b&amp;aacute;sicamente de los mismos objetos:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;RadialGradientBrush x:Key=&amp;quot;GlowFX&amp;quot; GradientOrigin=&amp;quot;.5,1&amp;quot; Center=&amp;quot;.5,1&amp;quot;&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;0&amp;quot; Color=&amp;quot;#990000FF&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;.5&amp;quot; Color=&amp;quot;#660000DD&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;1&amp;quot; Color=&amp;quot;#33000000&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;/RadialGradientBrush&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;El mayor cambio aqu&amp;iacute; es que ya no tenemos las propiedades StartPoint y EndPoint, en vez de estas tenemos GradientOrigin y Center. GradientOrigin define el punto desde el que se inicia el degradado, y Center define el punto que ser&amp;aacute; el centro del circulo externo que definir&amp;aacute; el degradado, en este ejemplo tienen valores id&amp;eacute;nticos&amp;nbsp; pero podr&amp;iacute;an ser distintos sin ning&amp;uacute;n problema.&lt;/div&gt;
&lt;div align="justify"&gt;Para aplicar estos recursos a una propiedad de un control basta con enlazar esa propiedad a un recurso est&amp;aacute;tico y especificar el nombre de nuestro degradado, de esta forma:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Button Content=&amp;quot;Hola&amp;quot; 
Background=&amp;quot;{StaticResource GlowFX}&amp;quot;&amp;gt;
&amp;lt;/Button&amp;gt;&lt;/pre&gt;
&lt;div align="justify"&gt;Por &amp;uacute;ltimo tenemos las animaciones, en mi caso las he usado para dar un efecto de activaci&amp;oacute;n al pasar el rat&amp;oacute;n sobre los controles o al recibir el foco ciertos controles usando el tabulador:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Storyboard x:Key=&amp;quot;GlowOut&amp;quot;&amp;gt;
&amp;lt;DoubleAnimation x:Name=&amp;quot;AnimGlowOut&amp;quot; BeginTime=&amp;quot;00:00:00&amp;quot; 
Storyboard.TargetName=&amp;quot;GlowRectangle&amp;quot; 
Duration=&amp;quot;00:00:00.250&amp;quot; From=&amp;quot;1&amp;quot; To=&amp;quot;0&amp;quot; 
Storyboard.TargetProperty=&amp;quot;Opacity&amp;quot;&amp;gt;
&amp;lt;/DoubleAnimation&amp;gt;
&amp;lt;/Storyboard&amp;gt;&lt;/pre&gt;
&lt;div style="text-align:justify;"&gt;&lt;/div&gt;
&lt;div style="text-align:justify;"&gt;Como podr&amp;aacute;s ver no es un xaml complicado, en primer Lugar definimos un objeto StoryBoard y le damos un nombre para poder invocarlo desde otros objetos. Este Storyboard contiene nuestra animaci&amp;oacute;n, en WPF existen muchos tipos distintos de animaci&amp;oacute;n, la primera parte del nombre indica el tipo de valor que es capaz de animar, en nuestro caso es un valor de tipo Double, pero podemos encontrar BooleanAnimation, CharAnimation, ColorAnimation y muchos m&amp;aacute;s tipos. Las propiedades que definimos son muy simples, name aplica un nombre a nuestra animaci&amp;oacute;n, BeginTime indica el momento despu&amp;eacute;s de invocar el storyboard en el que esta animaci&amp;oacute;n se iniciar&amp;aacute;, Duration indica el tiempo total que tomara nuestra animaci&amp;oacute;n para ejecutarse, la propiedad atada StoryBoard.TargetName indica el objeto sobre el que se aplicar&amp;aacute; la animaci&amp;oacute;n y StoryBoard.TargetProperty indica la propiedad de este objeto indicado que vamos a animar, por &amp;uacute;ltimo From y To indican el valor inicial y el valor final aplicado a esta animaci&amp;oacute;n. En este caso esta animaci&amp;oacute;n se aplicar&amp;aacute; a un objeto llamado GlowRectangle, y modificar&amp;aacute; gradualmente su propiedad Opacity en el transcurso de 250 milisegundos para llevarla desde 1 (totalmente opaco) a 0 (totalmente transparente).&lt;/div&gt;
&lt;div style="text-align:justify;"&gt;&lt;/div&gt;
&lt;div style="text-align:justify;"&gt;&lt;/div&gt;
&lt;div style="text-align:justify;"&gt;La aplicaci&amp;oacute;n de las animaciones se realiza a trav&amp;eacute;s de los disparadores de eventos (Event Triggers) de un control, en el pr&amp;oacute;ximo articulo lo explicar&amp;eacute; en m&amp;aacute;s detalle pero es algo as&amp;iacute;:&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;Button Name=&amp;quot;GlowRectangle&amp;quot; Content=&amp;quot;Hola&amp;quot;&amp;gt;
&amp;lt;Button.Triggers&amp;gt;
&amp;lt;EventTrigger RoutedEvent=&amp;quot;MouseLeave&amp;quot;&amp;gt;
&amp;lt;EventTrigger.Actions&amp;gt;
&amp;lt;BeginStoryboard Name=&amp;quot;{StaticResource GlowOut}&amp;quot;&amp;gt;
&amp;lt;/BeginStoryboard&amp;gt;
&amp;lt;/EventTrigger.Actions&amp;gt;
&amp;lt;/EventTrigger&amp;gt;
&amp;lt;/Button.Triggers&amp;gt;
&amp;lt;/Button&amp;gt;&lt;/pre&gt;
&lt;div style="text-align:justify;"&gt;A continuaci&amp;oacute;n os dejo un listado de todos los Degradados y animaciones que usaremos en este proyecto, para que pod&amp;aacute;is empezar a jugar con ellas y comprender su uso, en la segunda parte de este art&amp;iacute;culo entraremos directamente a ensuciarnos las manos creando los estilos de los controles.&lt;/div&gt;
&lt;div style="text-align:justify;"&gt;&lt;/div&gt;
&lt;div style="text-align:justify;"&gt;&lt;/div&gt;
&lt;div style="text-align:justify;"&gt;Espero que os sea &amp;uacute;til y os guste! Un gran saludo, nos vemos pronto.&lt;/div&gt;
&lt;pre class="brush: xml;"&gt;&amp;lt;!-- DARK BACKGROUND --&amp;gt;
&amp;lt;LinearGradientBrush x:Key=&amp;quot;DarkBackground&amp;quot; StartPoint=&amp;quot;0,0&amp;quot; EndPoint=&amp;quot;1,1&amp;quot;&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;0&amp;quot; Color=&amp;quot;#FF333344&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;1&amp;quot; Color=&amp;quot;#FF666677&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;/LinearGradientBrush&amp;gt;

&amp;lt;!-- GLASS EFFECT --&amp;gt;
&amp;lt;LinearGradientBrush x:Key=&amp;quot;GlassFX&amp;quot; StartPoint=&amp;quot;.5,0&amp;quot; EndPoint=&amp;quot;.5,.5&amp;quot;&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;1&amp;quot; Color=&amp;quot;#33DDDDDD&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;1&amp;quot; Color=&amp;quot;#33000000&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;/LinearGradientBrush&amp;gt;
&amp;lt;LinearGradientBrush x:Key=&amp;quot;GlassFXDisabled&amp;quot; StartPoint=&amp;quot;.5,0&amp;quot; EndPoint=&amp;quot;.5,.5&amp;quot;&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;1&amp;quot; Color=&amp;quot;#33BBBBBB&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;1&amp;quot; Color=&amp;quot;#11000000&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;/LinearGradientBrush&amp;gt;

&amp;lt;!-- GLOW EFFECT --&amp;gt;
&amp;lt;RadialGradientBrush x:Key=&amp;quot;GlowFX&amp;quot; GradientOrigin=&amp;quot;.5,1&amp;quot; Center=&amp;quot;.5,1&amp;quot;&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;0&amp;quot; Color=&amp;quot;#990000FF&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;.5&amp;quot; Color=&amp;quot;#660000DD&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;1&amp;quot; Color=&amp;quot;#33000000&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;/RadialGradientBrush&amp;gt;
&amp;lt;RadialGradientBrush x:Key=&amp;quot;GlowFXPressed&amp;quot; GradientOrigin=&amp;quot;.5,1&amp;quot; Center=&amp;quot;.5,1&amp;quot;&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;0&amp;quot; Color=&amp;quot;#660000CC&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;1.2&amp;quot; Color=&amp;quot;#33FFFFFF&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;/RadialGradientBrush&amp;gt;
&amp;lt;LinearGradientBrush x:Key=&amp;quot;GlowFXRowPressed&amp;quot;&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;0&amp;quot; Color=&amp;quot;#660000FF&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;.7&amp;quot; Color=&amp;quot;#660000AA&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;1&amp;quot; Color=&amp;quot;#66000000&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;/LinearGradientBrush&amp;gt;
&amp;lt;LinearGradientBrush x:Key=&amp;quot;GlowFXProgress&amp;quot;&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;0&amp;quot; Color=&amp;quot;#660099FF&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;.99&amp;quot; Color=&amp;quot;#660022AA&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;1&amp;quot; Color=&amp;quot;#00000000&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;/LinearGradientBrush&amp;gt;
&amp;lt;LinearGradientBrush x:Key=&amp;quot;GlowFXProgressAnimated&amp;quot; MappingMode=&amp;quot;RelativeToBoundingBox&amp;quot;&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;0&amp;quot; Color=&amp;quot;#00000000&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;.50&amp;quot; Color=&amp;quot;#660099FF&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;1&amp;quot; Color=&amp;quot;#00000000&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;/LinearGradientBrush&amp;gt;
&amp;lt;LinearGradientBrush x:Key=&amp;quot;GlowFXTabSelected&amp;quot; StartPoint=&amp;quot;.5,1&amp;quot; EndPoint=&amp;quot;.5,0&amp;quot;&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;0&amp;quot; Color=&amp;quot;#33DDDDDD&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;GradientStop Offset=&amp;quot;1&amp;quot; Color=&amp;quot;#332222FF&amp;quot;&amp;gt;&amp;lt;/GradientStop&amp;gt;
&amp;lt;/LinearGradientBrush&amp;gt;

&amp;lt;!-- GLOW ANIMATION --&amp;gt;
&amp;lt;Storyboard x:Key=&amp;quot;GlowOut&amp;quot;&amp;gt;
&amp;lt;DoubleAnimation x:Name=&amp;quot;AnimGlowOut&amp;quot; BeginTime=&amp;quot;00:00:00&amp;quot; 
Storyboard.TargetName=&amp;quot;GlowRectangle&amp;quot; 
Duration=&amp;quot;00:00:00.250&amp;quot; From=&amp;quot;1&amp;quot; To=&amp;quot;0&amp;quot; 
Storyboard.TargetProperty=&amp;quot;Opacity&amp;quot;&amp;gt;
&amp;lt;/DoubleAnimation&amp;gt;
&amp;lt;/Storyboard&amp;gt;
&amp;lt;Storyboard x:Key=&amp;quot;GlowIn&amp;quot;&amp;gt;
&amp;lt;DoubleAnimation x:Name=&amp;quot;AnimGlow&amp;quot; BeginTime=&amp;quot;00:00:00&amp;quot; 
Storyboard.TargetName=&amp;quot;GlowRectangle&amp;quot; 
Duration=&amp;quot;00:00:00.250&amp;quot; From=&amp;quot;0&amp;quot; To=&amp;quot;1&amp;quot; 
Storyboard.TargetProperty=&amp;quot;Opacity&amp;quot;&amp;gt;
&amp;lt;/DoubleAnimation&amp;gt;
&amp;lt;/Storyboard&amp;gt;&lt;/pre&gt;</description></item></channel></rss>