The solution to this recipe is an extension of the one introduced in Recipe 3.5, where we recommend writing code that generates some client-side JavaScript that calls the focus method of the desired control. For this recipe, we recommend adding some additional JavaScript-generating code that is tied to the Save button’s click event handler and that, when executed, searches for a control with a validation error and sets the focus to that control.
In the code-behind class for the page, use the .NET language of your choice to:
Write some code that is called from the Page_Load
method and generates a client-side JavaScript block that calls the
focus method of the desired control and sets the
control’s initial focus to itself (see Recipe 3.5 for details).
Add additional code to the Save (or equivalently named) button’s click event handler that searches for a control with a validation error and sets the focus to that control.
Use the RegisterClientScriptBlock
method of the
Page
object to register the script block so that
it is output when the page is rendered.
Example 3-19 and Example 3-20 show routines that are required to implement the last two steps of this solution.
As described in Recipe 3.5, you start implementing this solution by creating a client-side JavaScript block in the code-behind that sets the focus to a desired control and then outputs the block to the rendered page so that it is executed when the page is loaded. With this code in place, you can then add some additional code to the Save (or equivalently named) button’s click event that determines the first control with a validation error and sets the focus to it via the previously loaded JavaScript code.
This solution relies on the fact that the page object contains a
collection of the validation controls on the form. The order of the
validators in the collection is the same as the order in which they
appear in the .aspx
file. (The validators should
be placed with the controls they validate for this solution to work
correctly.)
To get a feel for how to implement this solution, first take a look at the sample application we created for Recipe 3.5 (Example 3-16 through Example 3-18). Next, consider the code in Example 3-19 and Example 3-20, which is added to that application to implement this recipe’s solution.
The way the additional code works is that when the server-side
button’s click event is executed, a check is first
made to see whether the page is valid. If it is, a save operation is
performed. If the page is not valid, the validators are iterated
through until the first invalid one is found. This is determined by
examining the IsValid
property of each validator
control; its value is false
if the control
associated with the validator has failed to pass validation.
When an invalid validator is found, the control it is associated with
is identified by calling the FindControl
method of
the Page
object. The control is then passed to the
setFocus
method. Only one control can have the
focus, so after an invalid control is found, the
for
loop is exited.
The client-side validation is disabled in this example to simplify the explanation of how to determine which control has a validation error and how to then set the focus to it. If we had kept client-side validation enabled, we would have also had to implement the same approach using client-side JavaScript. Although the latter may ultimately prove to be the most useful for you, we have avoided it here to keep this recipe relatively lean and to the point.
Example 3-19. Set focus to control with validation error (.vb)
Private Sub btnSave_Click(ByVal sender As Object, _ ByVal e As System.Web.UI.ImageClickEventArgs) _ Handles btnSave.Click Dim validator As System.Web.UI.WebControls.BaseValidator If (Page.IsValid) Then 'process form data and save as required for application Else 'page is invalid so iterate through validators to find the first one 'with an error For Each validator In Page.Validators If (Not validator.IsValid) Then 'validator that failed found so set the focus to the control 'it validates and exit the loop setFocus(Page.FindControl(validator.ControlToValidate)) Exit For End If Next validator End If End Sub 'btnSave_Click
Example 3-20. Set focus to control with validation error (.cs)
private void btnSave_Click(Object sender, System.Web.UI.ImageClickEventArgs e) { if (Page.IsValid) { // process form data and save as required for application } else { // page is invalid so iterate through validators to find the first // one with an error foreach(BaseValidator validator in Page.Validators) { if (!validator.IsValid) { // validator that failed found so set the focus to the control // it validates and exit the loop setFocus(Page.FindControl(validator.ControlToValidate)); break; } } } } // btnSave_Click