Hace un tiempo publique la entrada de Manejo de Propiedades en Silverlight, en ella hablaba de las grandes ventajas que podremos explotar por medio de esta herramienta, ahora en esta secuencia de post voy a hablar de las Dependency Properties, que son, cual es su diferencia con las propiedades ordinarias y como podemos sacarles la mayor ventaja posible.
Al hablar de propiedades, es muy fácil vincular los datos entre elementos y si tenemos un poco de experiencia en DataBinding definitivamente debemos aprender a usarlas pues son indispensables para muchos fines.
Vamos empezando por contestar algunas preguntas.
¿Qué son las dependency properties?
Son un tipo de propiedad pero que no solo devuelve un valor como las ordinarias, sino que además este valor depende de otros elementos, aquí es en donde se marca la principal diferencia, además de que tiene características adicionales como la autovalidación,
¿Desde cuando han sido implementadas?
Pertenecen de forma original a WPF apareciendo de la mano en el Framework 3.5, debido a que Silverlight originalmente derivó de WPF, estas fueron implementadas, hay que aclarar que en su versión 4 tienen una mejor funcionalidad.
¿Como implementarlas?
Bueno, pues vamos a la parte mas importante ver como utilizarlas, el propósito del ejercicio será que utilizando dos controles de usuario podamos enlazar una de sus propiedades por medio de un DataBinding en XAML.
El propósito de este artículo no es el de explicar el manejo de DataBinding pero un breve ejemplo nos dará un panorama mucho mas amplio.
Comienza creando una nueva solución, en este caso como ocasión especial lo haremos todo desde Visual Studio 2010 para hacerlo de una forma más cómoda.
Partiendo de la aplicación ya creada, lo primero que debes hacer es colocar únicamente dos cajas de texto dejando el XAML de tu MainPage de la siguiente forma.
<UserControl x:Class="Dependency_Properties.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" Height="300" Width="400"> <Grid x:Name="LayoutRoot" Background="LightGray"> <TextBox Height="28" HorizontalAlignment="Left" Margin="12,12,0,0" Name="textBox1" VerticalAlignment="Top" Width="150" /> <TextBox Height="28" HorizontalAlignment="Left" Margin="191,12,0,0" Name="textBox2" VerticalAlignment="Top" Width="150" /> </Grid> </UserControl> |
Y en el “textBox2”, enlaza la propiedad de texto con el “textBox1”, dejando la propiedad Text de la siguiente manera.
Text="{Binding Path=Text, ElementName=textBox1}" |
El resultado es simplemente sencillo, al escribir texto en la primer caja de texto, este se replicará automáticamente en la segunda caja de texto, puedes notarlo al correr la aplicación.
Ya después nos orientaremos mas al DataBinding, pero por ahora podemos continuar con el proyecto en cuestión.
Ahora crea un nuevo folder y ahí mismo crea dos controles de usuario, deja al final la solución de la siguiente manera.
El control de usuario “Control1” tiene en su XAML lo siguiente
<UserControl xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" x:Class="Dependency_Properties.Control1" HorizontalAlignment="Left" VerticalAlignment="Top"> <Grid x:Name="LayoutRoot" HorizontalAlignment="Left" VerticalAlignment="Top"> <TextBox x:Name="txtControl" HorizontalAlignment="Left" Height="28" TextWrapping="Wrap" VerticalAlignment="Top" Width="200" TextChanged="txtControl_TextChanged"/> </Grid> </UserControl> |
Y aquí vamos con la parte importante de esto, la implementación de la Dependency Property.
Primero como tip, te recomiendo que uses el snippet “propdp”, eso te va a ahorrar mucho tiempo y hará mas práctica implementación de la propiedad.
El resultado de ese snippet te dejará las siguientes líneas de código
public int MyProperty { get { return (int)GetValue(MyPropertyProperty); } set { SetValue(MyPropertyProperty, value); } } // Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc... public static readonly DependencyProperty MyPropertyProperty = DependencyProperty.Register("MyProperty", typeof(int), typeof(ownerclass), new UIPropertyMetadata(0)); |
Modifica las líneas para dejarlas de la siguiente manera
public string Texto { get { return (string)GetValue(TextoProperty); } set { SetValue(TextoProperty, value); } } public static readonly DependencyProperty TextoProperty = DependencyProperty.Register("Texto", typeof(string), typeof(Control1), new PropertyMetadata("")); |
Modifica las líneas para dejarlas de la siguiente manera
public string Texto { get { return (string)GetValue(TextoProperty); } set { SetValue(TextoProperty, value); } } public static readonly DependencyProperty TextoProperty = DependencyProperty.Register("Texto", typeof(string), typeof(Control1), new PropertyMetadata("")); |
Ahora bien, ¿qué hiciste? Pues creaste una propiedad de tipo string pero al momento de obtener el valor lo haces por medio de la propiedad de dependencia, esta a su vez recibe el valor como resultado de su método Register y le estás dando los parámetros que te solicita, el primero es simplemente el nombre, el segundo es el tipo de propiedad que vas a utilizar, el tercer parámetro es el tipo que registra a la propiedad y por último los metadatos de la propiedad de dependencia.
Por último utiliza el manejador del evento TextChanged de la caja de texto, para actualizar la propiedad con cada uno de los caracteres que le vayas insertando.
private void txtControl_TextChanged(object sender, TextChangedEventArgs e) { Texto = txtControl.Text; } |
Ahora es IMPORTANTE que construyas tu solución, y esto es porque el proyecto necesita actualizarse y saber que ya implementaste una propiedad de dependencia.
Ya que lo hiciste, ahora podrás hacer lo mismo que en el ejemplo anterior, es decir, enlazar la propiedad de texto de tu control recién creado con la propiedad de texto de un TextBlock, de la siguiente manera.
<Border BorderBrush="Black" BorderThickness="1" Margin="8,96,8,0" Height="74" VerticalAlignment="Top"> <Grid Margin="0"> <TextBlock Margin="8,8,0,0" TextWrapping="Wrap" Text="Ejemplo 2" HorizontalAlignment="Left" Height="17" VerticalAlignment="Top" Width="98"/> <local:Control1 x:Name="ctrl0" HorizontalAlignment="Left" Margin="8,0,0,8" VerticalAlignment="Bottom"/> <TextBlock x:Name="txtDestino" HorizontalAlignment="Right" Height="28" Margin="0,0,8,8" TextWrapping="Wrap" VerticalAlignment="Bottom" Width="200" d:LayoutOverrides="HorizontalAlignment, VerticalAlignment" Text="{Binding Texto, ElementName=ctrl0}"/> </Grid> </Border> |
Bien, hasta aquí hemos visto el concepto básico de las propiedades de dependencia, en el siguiente post veremos como manejarlas entre dos controles personalizados para no tener que pasar por la página principal y poder pasar la info sin problemas.
Puedes descargar el código fuente desde aquí.