Validating controls on a TabPage at one time using the Validating event
How do you Validate all of the controls on a TabPage at one time and set focus to one of the controls that fails validation?
Easy, use the TabPages Validating Event. Problem, this always sets focus to the control the user is currently on.
We have a Form. On this Form is a TabControl with a TabPage, and on the TabPage are two Textboxes (the app is much more complicated than this example).
There is a data validation requirement: the Textboxes need to either both have data or both be empty. This validation must be enforced *at the latest* when the user tries to leave the TabPage and not at the Textbox level (cannot use Validating on each textbox).
So far, so good, but there is one more requirement: if validation fails because one TextBox contains data and one does not, THE EMPTY ONE NEEDS TO
RECEIVE FOCUS, so as to prompt the user to enter data.
The solution thus far: handle the Validating event on the TabPage, check the values in the Textboxes, and if validation fails, notify the user with a MessageBox, set focus to the necessary TextBox using MyTextBox.Focus() and set the CancelEventArgs.Cancel = true to signal that validation failed. The Problem: the call to MyTextBox.Focus() seems to be ignored. The cursor remains wherever the user had it before the Validating event fired. Thus it seems the TabPage Validating event is firing at an odd times
The Solution:
Private Delegate Sub SetFocusDelegate(ByVal ctrl As Control)
Private Sub DoSetFocus(ByVal ctrl As Control)
ctrl.Focus()
End Sub
Public Sub SetFocusDeferred(ByVal ctrl As Control)
ctrl.BeginInvoke(New SetFocusDelegate(AddressOf DoSetFocus), New Object() {ctrl})
End Sub
Now, instead of calling Focus on control inside the TabPage validating event, call SetFocusDeferred passing the control as an argument. Because BeginInvoke will post a message, it'll set the focus after all other message handling has completed.
Many thanks to Ian Griffiths for his help on this one.