Monday, October 25, 2010

Forcing View Validation On Save using MVVM Pattren

In this post I will show you how to force the validation rules when user click on the save button without entering any thing in the user input form.Simple scenario is when user open the form and without entering any thing in the input control he/she press save button, if you see the UpdateSourceTrigger it has the default (The default value for most dependency properties is PropertyChanged, while the Text property has a default value of LostFocus.), explicit (Updates the binding source only when you call the UpdateSource method.), lost focus (Updates the binding source whenever the binding target element loses focus.) and property changed (Updates the binding source immediately whenever the binding target property changes.). If you didn't set default focus on any of the control when form open then lost focus of any of the control will not be fired and user didn't entered any value in the user input control so the property changed will also not fired So you have to check the validation rules before saving the user input form.
You have to check the user input validation on view, mean when user click the save button without entering anything in the input control then view should check if there are required field on the which need to be check before saving the form.Let us start with  the example code to force the validation of the input control from the view. For this I have used same example code which is used in the Range Validation Rule post, I have made some modification in the view model and also in the view so that when user click on the save button then the view will check the required field validation which is asked by the view model. Let us discuss what need to be done in order to ask the view to validate the user input.

View Model :
         In view model I have made the changes which are listed in the List 1. Here you can see that I have used the delegate which return the Boolean type and then In the CammandExecute I have call the ValidateView function to check the validation of the view.

public delegate Boolean dlgValidateView(); public dlgValidateView ValidateView; private void CommandExecute() { if (ValidateView()) { MessageBox.Show(Person.FullName); IsDialogClose = true; } else MessageBox.Show("Some Error on the View"); }
List 1

If the view is free of error then I will display the full name of the person as first and the last name of the person are required and then close the dialog. In the else statement I have just shown the message that there are some error on the view end. The dialog will only close if there is no error else if will not closed.

View :
     The code for the view is listed in the List 2, Here you can see that I have two sample of code which is of window loaded function and for the ValidateView function ( I have write code for one user id text box the remain code in the ValidateView is same).
In the loaded function I have check for the DataContext for not null and then assign the function ValidateVeiw function to the ValidateView of the view model which is set as data context of the Person view.

// window loaded code if (DataContext != null) ((PersonViewModel)DataContext).ValidateView = ValidateView; //Code for the Validate View function Boolean blnIsValid = true; BindingExpression bindingExpression; bindingExpression = txtUserID.GetBindingExpression(TextBox.TextProperty); if (bindingExpression != null) { bindingExpression.UpdateSource(); if (bindingExpression.HasError) blnIsValid = false; }
List 2

In the ValidateView function I have simple code, starting with the blnIsValid variable of type Boolean which is return from the ValidateView function and if any of the control has some error then blnIsValid variable is set to false to indicate that error on the view and the message is shown in the tool tip of the control.
Next is the BindingExpression object which is used to save the binding expression of the binding object in this case the objects are the text box controls. Next is to call the GetBindnigExpression of the user id text box control which Returns the BindingExpression that represents the binding on the specified property. Next is to check the binding expression for null if there is no active binding for the specified property in this case is the Text property which is passed to the GetBindingExpression.
If the binding expression is not null , mean the binding object has active binding then its time to update it, I have used the UpdateSource method Sends the current binding target value to the binding source property in TwoWay or OneWayToSource bindings. 

Image 1
After the UpdateSource function call next is to check the error by using the HasError property which will return true in case there is error after calling the UpdateSource function and then set the blnIsValid to false as the validation is fail. Some code is used for the first name, last name, email address and the contact number. By this way the view can tell the view model that there are some error in the view as user didn't entered any input in the control and is want to save the form.
Hope you get some idea about how to perform the validation on the when you are using the Validation rules.The output can be seen in the Image 1 which is displayed above when user open the form and want to save the form without entering any input.You can download the source code from here.  

All and any comments / bugs / suggestions are welcomed!


Anonymous said...

Nice example of validation for understanding purpose. Can you publish more on MVVM + Datagrid Binding + XmlData i/p file please....Waiting....

Asim Sajjad said...

@Anonymous : Thanks for your time and appreciation. It will be nice if you share your ideas as I have posted one post on binding data grid using MVVM

Anonymous said...

This is not MVVM!!!!!!