Jerry Nixon @Work: Mango Sample: Data Validation

Jerry Nixon on Windows

Wednesday, November 23, 2011

Mango Sample: Data Validation

imageWhoa! I am getting a lot of questions on data validation. This warrants an article. Of course, we have many choices. Some are prescriptive, some are simple, and some are just not reliable.

For now, I will just limit data entry to valid numbers. That doesn’t mean Char.IsNumeric. Commas and periods are valid. I also have to remember valid keys like shift, backspace, and tab.

Option 1: KeyDown

 
This is a good approach. It requires a lot of code. But, it is a well-proven strategy. All you do is evaluate the user’s keys and cancel the invalid ones. Your XAML might be like this:

image

Our code-behind could simple be:

image

In the code above, see where I call AddHandler()? This is important because not all keystrokes are bubbled to KeyDown. AddHandler works around this. And see e.Handled? Setting that to false cancels the keystroke. The logic in ParseDouble() is here.

Option 2: InputScope

 
InputScope controls the keyboard configuration. This should be part of other approachs. But, on its own, it’s problematic since it does not prevent users from entering (or pasting) invalid data.
InputScope is awfully easy to handle in XAML:

image

Option 3: BindingValidationError

 
Silverlight’s Binding Validation is another option. A property’s setter throws an exception if value is invalid. The binding catches this and raises BindingValidationError. You can handle this event to display an error message to the user.

image

Our XAML changes like this:

image

In the code above, see BindingValidationError attached to the StackPanel? Attaching to the StackPanel let’s me handle more than one TextBox. I would have attached to the TextBox. But, also notice ValidatesOnExceptions (by-passes the need to use ExceptionValidationRule explicitly) and NotifyOnValidationError. These are necessary.

With this code-behind:

image image

In the code above, we have a workaround? WPF has UpdateSourceTrigger=PropertyChanged (OnPropertyChanged in Windows Forms) that causes the underlying object to update as the user changes any part of the property’s value. Windows Phone does not support this. But this code makes it work. To validate as uses type, we need this. Otherwise we validate on Blur.

image

In the code above, we’re handling the error. The framework has “caught” the error for us, and bubbled it here. Using e.Action we can detect the new error. Using e.OriginalSource we can detect the specific TextBox (or any control) that caused it. Then, show the user the message.

image

In the code above, this is our sample DTO. It’s simple, eh? And, as you can see, all we do is raise an exception in the setter. No special interface. No special base class. No special exception. This is truly a great option for Silverlight developers.

Option 4: ExceptionValidationRule

 
Validation Rules (using ExceptionValidationRule) allow you to put rules outside the DTO and reuse them across controls. The rule itself is a custom class you use to determine validity.
Your XAML would look like this:

image

However, these are not supported in Windows Phone. Why even mention them? These are tools for WPF developers. It’s worth knowing what your limits are.

Option 5: Data Annotations

 
Data Annotations are custom attributes that decorate your classes and properties with things like Required, Range, Expressions, and Custom code. These are a big deal with ASP.Net & EF4.

Your Classes would look like this:

image

However, these are not supported in Windows Phone. Why mention them? These are very compelling validation tools. It’s worth knowing what your limits are.

Option 6: IDataErrorInfo

 
Remember BindingValidationError (Option 2)? Maybe you don’t want to throw errors. This interface is your answer. IDataErrorInfo is an extension using an error list instead exceptions.

The UI result is identical to Option 2:

image

The XAML is identical to Option 2:

image

The code-behind is not the same (but close):

image

In the code above, look at the setter. Where, in Option 2 we threw an exception when the parse failed, here we add to the error list (in our case a dictionary). You might be wondering about that Error property throwing a NotImplementedException? It turns out the interface includes that as a convenience to the developer (no thanks) and is not used by the Binding engine.

Option 7: INotifyDataErrorInfo

 
Here’s what MSDN says: In general, new entity classes for Silverlight should implement INotifyDataErrorInfo for the added flexibility instead of implementing IDataErrorInfo.

Well isn’t that a fine howdy-do? We go through all this work to use Data Binding validation only to be told we should use INotifyDataError. Then we go through all that work only to be told we should be using INotifyDataErrorInfo. Good news! This is it – the prescribed approach.

Why is this worthwhile? Well, let’s consider how IDataErrorInfo works. Right after the data value is set, the error list is queried. This expects the validation to nearly immediate. What if your validation took some time? You need an event, you need INotifyDataErrorInfo.

The UI looks the same (exactly):

image

The XAML looks the same (exactly):

image

Even the code-behind looks almost the same:

image
image

In the code above, there are only a few changes from the IDataErrorInfo implementation. Specifically, the presence of the ErrorsChanged event. This alerts the UI to “come look again!” for validation errors. Using this approach allows for validation to take as long as it needs – like calling to a service – using an async call.
Please note: I did not implement an async operation in my sample. For more on Windows Phone async operations, look at this article. For more information in calling out to a service, look at this article.

Option 8: Custom

 
How would this list be complete without a Custom solution? What if you are paid by the hour and want to build your own from scratch? Can you do that, too? The answer is no. There is no way to build custom validation on the Windows Phone platform. Ha! Just kidding, of course there is. But why? It doesn’t matter. Let’s do it!

Here’s the XAML:

image

In this sample we’re using attached properties – attached to the error label. The format and the textbox are specified. The code-behind does the rest – checking the value, adding the error message, changing the background color.

Here’s our code-behind:

image
image
image

In the code above, see the Setup() method? This is called by both properties because the they could be set in any order. But this is where we attach to the TextChanged event. In that handler, we test the format, and update the UI based on the result. And this is quite generic. I like it.

As an aside, in a WPF project we actually added a custom behavior to the TextBox control. This is yet another option for you. Actually, the sky is pretty much the limit for your custom solution.


Conclusion

 
WPF and Silverlight developers have a few more validation options than Windows Phone developer. Those are important to know – saving you time hunting. However, some techniques available to Windows Phone developers vary in support. Overall, the two best are KeyDown and INotifyDataErrorInfo. Each is well supported, proven, and useful. But if they do not fit the bill, you can build a custom solution.

Best of luck!