Hola a todos!
Este fin de semana he estado trabajando en una forma sencilla y reutilizable de validar datos en aplicaciones Windows Phone 8 y Windows 8. Los que hayáis desarrollado aplicaciones en Silverlight o WPF, recordaréis que al establecer un Binding podíamos añadir un atributo ValidateOnException y ValidateOnDataError. Esto hacía que automáticamente el control se enmarcase en rojo cuando existía un error o si se lanzaba una excepción al establecer el valor a la propiedad de la ViewModel.
Lamentablemente en Windows Phone 8 y Windows 8 Microsoft no ha incluido estos atributos (en serio… a veces hacen cosas incomprensibles…). Aunque existían varias formas de validar los datos, ninguna era tan sencilla de usar desde XAML como las anteriores, así que me puse manos a la obra para crear un sistema de validación que nos permita informar al usuario de que existe un error en los datos. Este sistema tenía que cumplir varios requisitos.
1) En primer lugar debería permitirme definir cuando se va a llevar a cabo la validación:
-
Automáticamente al cargar el control (Evento Loaded)
-
Cuando el control pierda el foco (Evento LostFocus)
-
Cuando el usuario presione sobre el control (Evento Tap/Tapped)
-
Cuando el usuario presione una tecla o la suelte (Eventos KeyDown y KeyUp)
-
Cuando el texto del control cambie (Evento TextChanged)
2) Además, me debía permitir definir el tipo de validación a realizar:
-
El texto no está vacío.
-
El texto es un número valido.
-
El texto no es un número.
-
El texto tiene un formato determinado, usando expresiones regulares.
3) Por último, debía poder obtener el estado de la validación en mi ViewModel de alguna forma, para actuar en consecuencia.
Aunque existen algunos validadores en NuGet, ninguno cumplía todos mis requisitos. Así que cree un nuevo proyecto en NuGet y me puse manos a la obra a crear un validador para Windows Phone 8 y Windows 8. El resultado creo que ha quedado bastante bien y sobretodo es muy sencillo de usar. pongamos el caso de que deseo validar que un usuario ha introducido su nombre. La validación que quiero realizar es que el texto no esté vacío y el momento en el que deseo hacerla es cuando el control pierda el foco. No quiero que se valide nada más entrar a la página. Con el validador que he creado, podríamos hacer algo parecido a esto:
1: <TextBox x:Name="textName">
2: <system:Interaction.Behaviors>
3: <val:TextBoxValidator ValidationFailed="{Binding NameValidationFailed, Mode=TwoWay}"
4: ValidateOnEvent="LostFocus"
5: ValidationPatternType="NotEmpty">
6: </val:TextBoxValidator>
7: </system:Interaction.Behaviors>
8: </TextBox>
Hacemos uso de un Behavior llamado TextBoxValidator con tres propiedades:
-
ValidationFailed, esta propiedad boolean nos indicará si se ha fallado o no la validación, podemos enlazarla a una propiedad de nuestra ViewModel para obtener el estado de cada validación.
-
ValidateOnEvent, nos permite indicar en que momento deseamos que se dispare la validación, podemos escoger entre: KeyDown, KeyUp, Loaded, LostFocus, Tapped o TextChanged.
-
ValidationPatternType, indicamos que validación queremos llevar a cabo: IsNumeric, NotIsNumeric, NotEmpty o RegExPattern.
Una vez indicadas estas tres propiedades, podríamos añadir un TextBlock debajo de nuestro TextBox que muestre la validación y que solo sea visible cuando se falle la validación:
1: <TextBlock Text="the name could not be empty." FontSize="24" Foreground="Red" Margin="12,0"
2: Visibility="{Binding NameValidationFailed, Converter={StaticResource BooleanToVisibilityConverter}}">
3: </TextBlock>
El resultado de este XAML sería el siguiente:
Lo que mas me gusta es que no tenemos que añadir nada de lógica en code behind, todo funciona simplemente desde XAML sin que nos tengamos que preocupar de ello.
Otro caso interesante es el de validar entradas más complejas como, por ejemplo, un correo electrónico o un campo alfanumérico con un formato específico. Para esto, vimos que uno de los valores permitidos en la propiedad ValidationPatternType era RegExPattern.
Si indicamos este tipo, podremos indicar una cuarta propiedad llamada RegExPattern, en la que podremos indicar una expresión regular que el validador usará con el valor del texto. Si se encuentra al menos una coincidencia, se pasa la validación:
1: <TextBox x:Name="textEmail">
2: <system:Interaction.Behaviors>
3: <val:TextBoxValidator ValidationFailed="{Binding EmailValidationFailed, Mode=TwoWay}"
4: ValidateOnEvent="LostFocus"
5: ValidationPatternType="RegExPattern"
6: RegExPattern="^[_a-z0-9-]+(.[_a-z0-9-]+)*@[a-z0-9-]+(.[a-z0-9-]+)*(.[a-z]{2,4})$">
7: </val:TextBoxValidator>
8: </system:Interaction.Behaviors>
9: </TextBox>
10: <TextBlock Text="failed!" FontSize="24" Foreground="Red" Margin="12,0"
11: Visibility="{Binding EmailValidationFailed, Converter={StaticResource BooleanToVisibilityConverter}}">
12: </TextBlock>
En este caso validamos un formato de correo electrónico, de forma sencilla y directamente desde XAML.
Si queréis usar estos validadores en vuestros proyectos, los podéis descargar desde NuGet directamente. Existe una versión para Windows Phone 8 y otra para Windows 8.
El uso de ambos es completamente igual. El mayor cambio es el soporte a los Behaviors. Mientras que en Windows Phone 8 se incluyen dentro de System.Windows.Interactivity, en Windows 8 tenemos que usar la librería WinRTBehaviors de mi buen amigo y Windows Phone MVP @Localjoost.
Si queréis ver el código fuente de ambos proyectos, podéis hacerlo desde Nokia Projects: https://projects.developer.nokia.com/input_validations, incluso podréis descargar el código usando GIT.
Por último, he creado dos ejemplos de como usar estos validadores, uno para Windows Phone 8 y otro para Windows 8, que también podéis descargar desde Nokia Projects: https://projects.developer.nokia.com/input_validations/files/downloads. Y con esto termino. Espero como siempre que os sea muy útil y que lo implementéis en muchos productos (y si lo hacéis, hacédmelo saber, principalmente por ego jejeje).
Un abrazo a todos y Happy Coding!!
Te presentamos nuestra colección de Tips & Tricks de desarrollo de apps para Windows Phone