Entre todas las cosas que me gustan de WPF, una de las que más, es la versatilidad, los programadores podemos hacer practicamente lo que queramos. Hace unos «pocos» años, el programador debía servirse de controles de otras empresas porque a veces, los controles básicos de Microsoft se quedaban «cortos» para cuestiones más complejas; posteriormente, se podían crear controles de este tipo pero para que funcionaran (como deben funcionar), había que afinar mucho, pero la facilidad con la que se puede crear y la complejidad que se le puede dar a un control actualmente es bestial. Para que se hagan una idea, en mis proyectos tengo un control de usuario creado sobre una clase Persona estándar, de modo que cada vez que tengo que iniciar un proyecto en el que esa clase hace acto de presencia, el control con sus binding lo hace de igual modo y ya es cuestión de adaptar si queremos que aparezca tal propiedad o no, pero las validaciones de datos como DNI, cuenta bancaria, tarjetas,etc, los cálculos (por ejemplo la edad), las máscaras de entrada, editar y guardar, marcas de edición, etc., es decir un sinfín de procesos, se encuentran hechos. Solo nos quedaría, darle forma a la interfaz gráfica para adaptarla a las necesidades del cliente.
Un control de usuario podría ser, una control ListView con cada uno de sus items que fueran un Treeview por ejemplo, podríamos crear un control ProgressBar con varios colores como un vumeter, un Progressbar circular, un TextBox inteligente que nos ayude a escribir, podríamos crear un control que realice funciones de filtrado sobre un contenido de registros, dándole una colección de entrada y entregando una colección de salida con los parámetros de filtrado, podríamos crear un reloj analógico como control, un reloj binario, un lo que se nos venga a la cabeza, esa es su función, crear objetos complejos en base a otros controles.
En este artículo, como ejempo vamos a mostrar un control básico que hará las siguientes funciones:
- Control slider
- Debe iluminarse la zona que hemos desplazado con el cursor
- Debe aparecer un texto con el valor
- Dependiendo del valor, debe cambiar su color
Vamos a ver el código XAML
<UserControl x:Class="Controls.SliderUserControl" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:local="clr-namespace:Controls" mc:Ignorable="d" d:DesignHeight="40" d:DesignWidth="300"> <StackPanel> <Grid> <Grid.Resources> <local:ValueToBrush x:Key="vtb"/> </Grid.Resources> <ProgressBar Minimum="{Binding ElementName=mainSlider,Path=Minimum}" Maximum="{Binding ElementName=mainSlider,Path=Maximum}" Value="{Binding ElementName=mainSlider, Path=Value}" Height="10"/> <Slider x:Name="mainSlider" Maximum="100" Minimum="0" Value="30" BorderBrush="Gray" BorderThickness="1" Background="{Binding ElementName=mainSlider,Path=Value,Converter={StaticResource vtb}}" Opacity=".2"/> </Grid> <TextBlock Text="{Binding ElementName=mainSlider, Path=Value, StringFormat={}{0:N0}}" HorizontalAlignment="Center" FontSize="16"/> </StackPanel> </UserControl>
Analizando el código, creamos un slider que veremos con más detenimiento, un control progressbar que nos indicará visualmente el valor del slider y un TextBlock.
El control ProgressBar le hacemos un binding a la propiedad Maximun, Minimun y Value a las mismas propiedades del control Slider.
El control TextBlock le hacemos un binding a la propiedad Text pero dándole formato para que no aparezcan decimales.
El control Slider tiene alguna cosa más y es que la propiedad Opacity la hemos bajado a 0.2 y la propiedad Background se alimenta de la propiedad Value la cual es convertida en un objeto Brush desde una clase que implementa IValueConverter
llamada ValueToBrush
. Esta clase es instanciada desde el código XAML y la llamamos en el binding de la propiedad Text.
public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { if ((double)value < 50) { return Brushes.Green; } else if ((double)value < 75) { return Brushes.Yellow; } else { return Brushes.Red; } }
de este modo cambia de color dependiendo del valor.
El resultado es el siguiente:
Lo mejor de todo, el control sin una sola línea de código (sin contar el converter 😉 ). En próximas ediciones, algún control más complejo.
Un saludo