Friday, March 9, 2012

Windows Phone form validation

I've spent a lot more time than I had expected these last two days trying to figure out the best way to do form validation on Windows Phone. In the app that I'm working on there is a registration flow and at one point the user needs to provide a user name, password and some other information. All of this data need to be validated before sent to the server and if something is missing or incorrect (invalid e-mail address or a password and password confirmation isn't matching) I need to present this to the user.

On Android I would do something like:

  1. Listen to the Register button click or if I want early validation listen to text or focus change (TextWatcher or OnFocusChangeListener) on the fields in question
  2. Validate the input
  3. Call setError(string) on the invalid fields. Doing this: "Sets the right-hand compound drawable of the TextView to the "error" icon and sets an error message that will be displayed in a popup when the TextView has focus. The icon and error message will be reset to null when any key events cause changes to the TextView's text"
This will result in something like this:


Three simple steps and you get everything you need. Easy. Now how is something like this done on Windows Phone? It turns out that there's quite a few more steps involved and many pitfalls on the way...

Windows Phone does support data validation when working with data bindings and the system is pretty powerful, but in my opinion lacking in a key area, namely a way to present validation errors in a standardized way like on Android. So, how does the data validation work? If you look at the documentation referenced by Microsoft's own Eric Fleck you'll see that there's simple data validation in two-way data bindings and additional support using IDataErrorInfo and INotifyDataErrorInfo. There's also an example of how the user feedback might look like:

That looks fine and dandy and just what I needed. My first attempt at achieving this was to use simple data validation by raising an exception in the data bound setter and specifying in my XAML that the field will validate on exceptions:



And in my setter in the ViewModel:


private string _UserName;
public string UserName
{
set
{
if(IsInvalidEmail(value)
{
throw new Exception("You must enter a valid e-mail address");
}
_UserName = value;
}
get
{
return _UserName;
}
}


This looks like a very nice way of handling form validation and it doesn't really require a lot of work, but the problem is that I did not get the nice little tooltip when I entered an incorrect e-mail address. My first thought was of course that there was something wrong with my binding or that the exception wasn't handled properly. I did however manage to verify that the validation was working by providing an event listener via the BindingValidationError property. If you add an event listener and make sure you have NotifyOnValidationErrors=True you'll trigger the event each time you come across a validation error. 


As a side note: It took me a while to figure out how to add a data binding to the BindingValidationError property (I'm trying to be a good MVVM boy here and leave my code behind as clean as possible) since you cannot bind to events out of the box. You need to use BindEventToCommand from MVVM Light to get this working.

Ok, back to my missing tooltip. I did a great deal of Googling and read numerous blog posts about data validation where examples of data validation with tooltip feedback was used, but the more I read the more unsure I became if this really was supported on Windows Phone and not only present in Silverlight on the web. I finally came across indication that this was the case. Eric Fleck (again) posted (although admittedly one year before the post mentioned above) that "the standard control templates do not act upon the ValidationStates and this is why nothing appears to happen when you set ValidatesOnException to true". Eric continues by saying that "you can override a control template to add ValidationStates", but at this point I'm losing hope of an easy solution using ValidatesOnException and I abandon the whole thing and look at an alternative.

What I end up doing is that I add validation feedback as textblocks below each textbox and by default set their visibility to collapsed (i.e. not visible). I then databind the visibility of the feedback texts to properties such as IsInvalidUserName, IsPasswordsNotMatching and so on in my view model and use a data binding converter to convert from booleans to Visibility (Visible and Collapsed).

One of my biggest take-aways from all of this is that the Windows Phone documentation is lacking in some key areas and that it many times is extremely hard for a new Windows Phone developer to actually know if documentation and examples are valid for WP and not only for Silverlight on the web. The Windows Phone development quickstarts are good and very clear, but they often don't go into enough detail and this is the times when I've found myself in the wrong place reading the wrong documentation.

A final remark: Does tooltips actually work on windows phone? You can set  ToolTipService.ToolTip="Some text" and  ToolTipService.Placement="Right" on any control in your XAML, but I have so far never been able to display one.

1 comment:

  1. Check out the following link on for more article on windows phone development.....
    http://www.mindstick.com/Articles/50b715de-64da-40dc-9ad9-f397a6739d66/?Password%20Control%20in%20Windows%20Phone%207%20Development

    ReplyDelete