This is the sixth posting in a series on Templates and DataValidation.
[ First In Series Previous In Series ]
In this posting I’ll extend the data validation mechanism we’ve been examining to support asynchronous data validation (allowing for validation by objects on a web service).
Silverlight is all about client-side code, and client-side validation is often exactly what you want; however there are times that you do not want to expose your validation algorithm in the client or in which you need to do a dynamic database lookup (credit ratings come to mind). In that case, you’ll want your Silverlight application to be able to validate against a web service, but to keep working while it does so. That’s just what we’ll do today.
To save time I’ll build on a variation of the project we’ve been looking at. There are no surprises in that code, and you can download the source code for both the starting and the ending project.
To review, briefly, MainPage invokes EditCustomer. The contents of EditCustomer’s input controls are filled via databinding, which includes the two attributes needed for data validation. For example, the Zip Code text box looks like this:
<TextBox x:Name = "Zip" Width = "80" Text = "{Binding Path=Zip, Mode=TwoWay, ValidatesOnExceptions=true, NotifyOnValidationError=true}" Style = "{StaticResource NarrowTextBoxStyle}" />
Validation Logic In the VM
All of the client side validation logic is in the View Model. For example, here is the logic for the State field validation:
private string state; public string State { get { return state; } set { var stateErrors = new List<String>(); if (string.IsNullOrEmpty(value)) { return; } AddLogItem("Testing State for 2 characters"); if ( value.Length != 2) { stateErrors.Add( "State must be two letters" ); AddLogItem("ERROR State was not 2 characters"); ManageErrors("State", stateErrors); } else { ManageErrors( "State", null); state = value; AddLogItem("State accepted"); RaisePropertyChanged("State"); } } }
As discussed earlier in this series, the validation is done in the setter of the property. In this case, I’ve factored out the management of the dictionary of errors to the ManageErrors method. ManageErrors job is either to add the property to the dictionary of errors if the entry is not valid, or to remove it from the dictionary if it is already there but the field is no longer invalid.
private void ManageErrors( string property, List<String> errors ) { var raiseEventErrorsChanged = false; if ( property == null ) { return; } if ( errors == null ) { if ( currentErrors.ContainsKey( property ) ) { AddLogItem( "Clearing errors for " + property ); currentErrors.Remove( property ); raiseEventErrorsChanged = true; } AddLogItem( "Set Status OK" ); } else { AddLogItem( "Writing error for " + property ); currentErrors.Add( property, errors ); AddLogItem( "Set Status Error" ); raiseEventErrorsChanged = true; } if ( raiseEventErrorsChanged && ErrorsChanged != null ) { AddLogItem( "Invoking ErrorsChanged with " + property ); ErrorsChanged( this, new DataErrorsChangedEventArgs( property ) ); } }
To add asynchronous support for checking against a web service we’ll add four elements to the program:
- A (mock) web service
- A callback method to receive the decision from the web service (valid or not valid?)
- An enumerated set of states to indicate to the user if the field is valid or not or if we’re waiting for a response
- A public property indicating the current status (to which the UI can bind)
Modifying The Validation To Call Out To The Web Service
After we’ve done all the local validation work we can, the State property will call out to the Web Service, passing in a copy of the value that is being evaluated, and an instance of a CustomerCallBack delegate,
public delegate void CustomerCallBack( bool isValid );
Specifically, one which will cause the web service to call the method StateCallMeBack when it has validated the value.
In the demo code, I mock up the web service to delay for a random but constrainted amount of time; then it invokes the callback method through the delegate, passing as a parameter a boolean that is randomly set either true or false.
private static void TimeElapsed( object sender, EventArgs e) { var t = sender as DispatcherTimer; if (t == null) { return; } t.Stop(); var custCallBack = CallBacks[t]; var isValid = RandomGenerator.Next()%2 == 0; custCallBack(isValid); }
The callback method itself acts just like any other local validating method, checking the truth of its if statement and either adding or clearing the error,
public void StateCallMeBack( bool isValid ) { AddLogItem( "In call back from Web Service" ); ErrorCheckingStatus = Status.Completed; if ( isValid ) { AddLogItem( "Web service reported OK" ); ManageErrors( "State", null ); state = candidateNewState; ErrorCheckingStatus = Status.Ok; RaisePropertyChanged( "State" ); } else { AddLogItem( "Web service reported error" ); var callBackErrors = new List<String>(); const string info = "Your entry does not match a US State"; callBackErrors.Add( info ); ErrorCheckingStatus = Status.Error; ManageErrors( "State", callBackErrors ); } ErrorCheckingStatus = Status.Completed; }
Asynchronous Means Never Having To Say You’re Blocked…
While the web service is processing the validity of the data you are free to go on and check the validity of other fields. The status will be set to In Progress and nothing will be blocked. When the web service completes the call back will be invoked and will set the state appropriately. Notice that the log shows that the request was made to the server, and then the program went on to test the Zip Code which fails the test, and the appropriate error is displayed.
A Personal Note
On a personal note, I was very pleased to see Silverlight build on Styles and Templates to add the Visual State manager, and then build on the Visual State Manager and databinding to build data validation. This is a strong indication of a powerful an flexible architecture, and I believe it bodes well for continuing development.
In the next posting, I’ll take a look at how you can use the Visual State Manager to change how the error message appears.
Note that this week marks the launch of a new and on-going series of tutorials and videos on Windows Phone 7 Programming. If there are topics of specific interest to you, please do leave a comment.
If you are interested in topic: earn online by clicking while breastfeeding – you should read about
Bucksflooder first
Very informative article, i am regular reader of your site.
I noticed that your website is outranked by many
other websites in google’s search results. You deserve to
be in top-10. I know what can help you, search in google for:
Omond’s tips outsource the work
Outstanding post but I was wondering if you could write a
litte more on this topic? I’d be very thankful if you
could elaborate a little bit more. Cheers!
You are so interesting! I do not believe I’ve read a single
thing like this before. So nice to find another person with some genuine thoughts on this topic.
Seriously.. many thanks for starting this up. This website
is something that is needed on the internet, someone with a
little originality!
I can’t find that next posting. Did you forget to publish it?
Very good tutorial
I am really enjoyed reading your articles, I am a newbie and I love to learn new things about world and people relationship.
Good! Very good article! thanks!!!