I have a little form with some text boxes and combo boxes, each with their own validating event which just fills the default value either 1 or 0 depending on the box when the user moves on to the next box without entering anything, however i also want to run all the validations when the user just clicks on the submit button directly.
private void Validating_Zero(object sender, CancelEventArgs e)
{
if (((TextBox_Pro)sender).Text == "")
{
((TextBox_Pro)sender).Text = "0";
}
}
private void Validating_One(object sender, CancelEventArgs e)
{
if (((TextBox_Pro)sender).Text == "")
{
((TextBox_Pro)sender).Text = "1";
}
}
private void Start_Validating(object sender, CancelEventArgs e)
{
}
Calling ValidateChildren() method of the form, cause all of the child controls of the form to validate their data.
You can also use the the other overload of the method which accepts a validation constraint, ValidateChildren(ValidationConstraints) to limit the validation to immediate child controls, enabled controls, tab stop controls, selectable controls, visible controls or all control.
To see an example of validation using Validating event and Error provider control and showing error summary and also read more about validation options in Windows Forms, take a look at these posts:
Validating user input / Give .NET controls status OK or NOK
Validation using Validating event and ErrorProvider - Show Error Summary
Related
I am trying to follow the MSDN example code for the Control.Validating Event and to apply it to a bindingNavigator item instead of the textbox as in the example.
The code provided for the textbox validation event is shown below.
private void textBox1_Validating(object sender,
System.ComponentModel.CancelEventArgs e)
{
string errorMsg;
if(!ValidEmailAddress(textBox1.Text, out errorMsg))
{
// Cancel the event and select the text to be corrected by the user.
e.Cancel = true;
textBox1.Select(0, textBox1.Text.Length);
// Set the ErrorProvider error with the text to display.
this.errorProvider1.SetError(textBox1, errorMsg);
}
}
I too intend on validating texboxes however I have several and have already written the validation methods for them which handle the error messages. I would like these methods to be tested when the user selects an item (Arrow buttons / Save button / Add button) on the bindingNavidator.
I therefore have the code below to attempt this,
private void myBindingNavigator_Validating(object sender, CancelEventArgs e)
{
if (!IsPostCodeValid())
{
PostCodeTextBox.Focus();
e.Cancel = true;
}
}
I have the ItemClicked event for the bindingNavigator set to bindingNavigator.Focus() with the hope of initiating the Validating event. (myBindingNavigator.CausesValidation = true; has been declared on formLoad). However I feel this is where an infinite loop of focusing the Navigation bar follows? I have stepped through and no code is executed once it has locked on to the Navigation bar it simply won't let the user interact with the rest of the form to change and correct the error after the navigation bar has been locked onto.
I can provide any extra information required and test any suggestions to discover what is going on.
Thanks
When you work with BindingNavigator and you have put your controls in details mode on the form, to ensure save only valid data, you should write validation rules for your controls and also you should handle your binding navigator items yourself.
This way you even don't need to set AutoValidate Property of your form to annoying EnablePreventFocusChange and you can set it to be the friendly EnableAllowFocusChange and because you can't navigate or save anything when there is validation errors, then you can be sure only valid data will save in database.
To do so, follow these steps:
Step 1
Handle Validating event of child controls and set e.cancel = true when the value is not valid.
private void nameTextBox_Validating(object sender, CancelEventArgs e)
{
//Put validation logic here
if (this.nameTextBox.Text.Length < 10)
{
e.Cancel = true;
this.errorProvider1.SetError(this.nameTextBox, "Some Error");
}
else
{
this.errorProvider1.SetError(this.nameTextBox, "");
}
}
Step 2
Go to BindingNavigator properties, and set MoveFirstItem, MovePreviousItem, MoveNextItem, MoveLastItem, AddNewItem, DeleteItem properties To (none). Also from designer click on the text box that shows record number, it is bindingNavigatorPositionItem, and then set its ReadOnly property to true.
Step 3
For all buttons, including navigation buttons, add button, delete button, save button and other custom buttons, handle Click event and call ValidateChildren method of the container of your text boxes and check if ValidateChildren() doesn't return true, exit the method, else do the task that the method should do, for example:
private void toolStripButton1_Click(object sender, EventArgs e)
{
if (!this.ValidateChildren())
return;
//Put the logic for this button here
//MoveFirstItem: `this.myBindingSource.MoveFirst();`
//MovePreviousItem: `this.myBindingSource.MovePrevious();`
//MoveNextItem: `this.myBindingSource.MoveNext();`
//MoveLastItem: `this.myBindingSource.MoveLast();`
//AddNewItem: `this.myBindingSource.AddNew();`
//DeleteItem: `this.myBindingSource.RemoveCurrent();`
}
This is a winform C# question. I have a textbox with a validating event listener to validate the content of the textbox against a regular expression.
After the validation, if entered value is not proper,i am showing the messagebox and i am cancelling the event so that mouse cursor move back to the textbox which has improper value.
This is working fine when i move out from that textbox to other buttons/textboxes.
But when i enter improper value and close the form (with the close button on right top corner), it validates the textbox contents and throws up the messagebox and form doesnot close as i am cacelling the event.
The problem is, when I click the X button on the right top corner of the form, I don't want the validation to be fired because I am closing the form anyway. How can I do this?
I will post the code snippet as soon as possible.
To use validating handlers such as the 'txtIPAddress_Validating()' handler below while being able to close the form without having to enter valid entries to do so, I do the following:
1) Initate validating handlers:
From the control properties of the control you wish to activate validation for, double click the 'Validating' event from this control event list. A control event list is accessed by clicking this control's property sheet’s event (lightning looking) toolbar button. You can then enter the code in the automatically generated handler with a name combining both the name of the control and '_Validating'. The part of this handler where something is established as invalid can force valid entries by adding the 'e.Cancel = true' instruction.
For such validating method examples, See 'txtIPAddress_Validating()' and 'txtMaskBits_Validating()' code below. Do not get distracted by the complete validation mechanism of these specific examples. All you need to see and reproduce in your own code in order to force validation is to add the 'e.Cancel = true' instruction at the right place of your own validating method. That is when the value is identified to be invalid.
At this point the validation should work fine but any attempt to close the form will trigger validation which will stop and insist for valid values before being able to close the form. This is not always what you want. When it is not so, I continue with the following.
2) 'Cancel' button that also cancels (disables) all validations:
a) Place a regular 'Cancel' button on the form which is associated to a method such as the 'btnCancel_Click()' method below.
b) Before the regular 'this.close();' instruction, add the 'AutoValidate = AutoValidate.Disable;' instruction. This instruction disables all 'validating' triggers. Note that the 'btnCancel_Click' event is triggered before any validation is taking place. That is not so for the Form Closing events that will all execute after validating events. That is why that validation cannot be disabled from any of these Form Closing events.
c) For this 'Cancel' button to work correctly, you also need to set the 'CausesValidation' property of this 'Cancel' button to 'false'. This is necessary, otherwise clicking on this button will trigger the validation before validating can be disabled by the above 'AutoValidate = AutoValidate.Disable;' instruction.
At this point, you should be able to quit by clicking on the 'Cancel' button without having to first enter valid values. However, clicking the upper right "X" button of the form's window will still force validation.
3) Make the upper right "X" button also cancel validation:
The challenge here is to trap such "X" clicked event before validation is executed. Any attempt to do so through a Form Closing handler will not work because it is then too late once execution reaches such handler. However, the click of the "X" button can be captured promptly via overriding the WndProc() method and testing for a 'm.Msg == 0x10' condition. When that condition is true, the previously introduced 'AutoValidate = AutoValidate.Disable;' instruction can again be used to disable overall validation in that case as well. See the WndProc() method below for a code sample of such method. You should be able to copy and paste that method as is in your form's class.
At this point, both the 'Cancel' an "X" buttons should cancel valdations. However, the escape key that can be used to close a form does not. Such escape key is activated when the form's 'CancelButton' property is used to link this escape key to the form's 'Cancel' button.
4) Make the escape key also cancel validation:
Similar to the "X" button, the escape key can be captured by overriding an existingmethod. That is the ProcessDialogKey() method. One more time, the previously introduced 'AutoValidate = AutoValidate.Disable;' instruction can be used to disable overall validation for the escape key as well. See the ‘ProcessDialogKey()’ overridden method in the code below to see how this can be done. Here again, you should be able to copy and paste that method as is in your own form's class.
At this point you should be done!
Further considerations:
It is good to notice that the following two other ways to close the window should also work fine at this point. These two ways are:
The 'Close' option of the upper left window icon button.
Pressing Alt+F4 which triggers the same closing action as the above 'Close' option.
These two ways of closing the window started to also cancel validation once you introduced the "X" button capture mechanism described in point 3 above.
That is it for me for this so far. Hoping this helps!
My code sample below:
public partial class frmMyIP : Form
{
public frmMyIP()
{
InitializeComponent();
}
// To capture the Upper right "X" click
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x10) // The upper right "X" was clicked
{
AutoValidate = AutoValidate.Disable; //Deactivate all validations
}
base.WndProc(ref m);
}
// To capture the "Esc" key
protected override bool ProcessDialogKey(Keys keyData)
{
if (keyData == Keys.Escape)
{
AutoValidate = AutoValidate.Disable;
btnCancel.PerformClick();
return true;
}
return base.ProcessDialogKey(keyData);
}
public bool IsValidIP(string ipaddr)
{
string pattern = #"^([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])"+
#"(\.([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])){3}$";
Regex check = new Regex(pattern);
bool valid = false;
if (ipaddr == "")
{
valid = false;
}
else
{
valid = check.IsMatch(ipaddr, 0);
}
return valid;
}
private void txtIPAddress_Validating(object sender, CancelEventArgs e)
{
string address = txtIPAddress.Text;
if (!IsValidIP(address))
{
MessageBox.Show("Invalid IP address!");
e.Cancel = true;
}
}
private void cmbMaskBits_Validating(object sender, CancelEventArgs e)
{
int MaskBitsValue = Convert.ToInt32(cmbMaskBits.Text);
if (MaskBitsValue<1 || MaskBitsValue>30)
{
MessageBox.Show("Please select a 'Mask Bits' value between 1 and 30!");
e.Cancel = true;
}
}
private void btnCancel_Click(object sender, EventArgs e)
{
// Stop the validation of any controls so the form can close.
// Note: The CausesValidation property of this <Cancel> button
// must also be set to false.
AutoValidate = AutoValidate.Disable;
this.Close();
}
Insert the following as the first line in the validation event of the textbox:
//Allow the form to be closed
if (this.ActiveControl.Equals(sender))
return;
Since the close event of the form is triggering validation and since that would (typically at least) be the only form event that would trigger validation we can make the assumption that any form event triggering validation is the close event.
The actual answer is ridiculously simple compared to all the suggestions here which involve hacks and extra superfluous code to undo something.
The "trick" is just to allow the focus to change and not fire validation from buttons on the form itself.
You can simply set two properties on the form:
MyForm.CausesValidation = false;
MyForm.AutoValidate = AutoValidate.EnableAllowFocusChange;
Et voila, form acts normal when you try to close it and validation still works following other inputs such as tab changing focus or mouse clicks.
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
// Assume that X has been clicked and act accordingly.
}
Create a closing event, then simply cancel your validator.
Try to set CauseValidation to false
or see here : How to skip Validating after clicking on a Form's Cancel button
Or try set this in formClosing event
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
// CauseValidation to false or check
}
What you need is an implementation like the one described below, where it is assumed that you have a Save button and a Cancel button for the form:
public Form1()
{
// Disable validation in constructor
textBox.CausesValidation = false;
}
private void OnSaveClicked(object sender, EventArgs e)
{
textBox.CausesValidation = true;
if (ValidateChildren())
{
//
// Do saving of the form data or other processing here ....
//
Close();
}
//
// Set validation to false, as user may press Cancel next
//
textBox.CausesValidation = false;
}
private void OnCancelClicked(object sender, EventArgs e)
{
Close();
}
Check which button has focus in the validation check. If cancel button (and in my case a clear button), override. This is an inner method I call from my cell validating event handler. (Just realized it was a C# question, but you can translate)
Private Sub validateCell(ByVal tagDesc As String, ByVal userInput As String, ByVal legalRegex As String, ByVal regexDesc As String, ByVal e As DataGridViewCellValidatingEventArgs)
Dim match As Match = Regex.Match(userInput, legalRegex)
Dim matches = match.Groups()
Dim val = match.Value
If val.Length = 0 Or userInput.Length > val.Length Then
tagGrid.Rows(e.RowIndex).ErrorText = _
tagDesc & " must match pattern: " & regexDesc
If Me.Cancel_Button.Focused Or Me.clearButton.Focused Then
e.Cancel = False
tagGrid.Rows(e.RowIndex).ErrorText = ""
Else
e.Cancel = True
MsgBox(tagDesc & " must match pattern: " & regexDesc, MsgBoxStyle.Critical)
End If
Else
e.Cancel = False
tagGrid.Rows(e.RowIndex).ErrorText = ""
End If
End Sub
I came here in search of a simple method to cause a form to close when a Validating event handler raises an exception, reports it, and needs to force the form to close. After reading this topic and numerous others, followed by an afternoon of experimenting, I have made several discoveries, and developed a simple hack to force the form to close.
First things first, though; I discovered that when a Validating event calls this.Close() the FormClosingEventArgs.Cancel flag passed into its From_Closing event procedure is set to TRUE, effectively causing the event to cancel itself. Conversely, a normal Close event receives a FormClosingEventArgs.Cancel flag set to FALSE.
Since the Close method on a form takes no arguments, there is no direct way to force the issue, giving rise to the need for a hack. This article discusses a number of such hacks, but I think mine is much simpler to implement.
The hack starts with a simple form level Boolean variable.
bool _fExceptionIsFatal = false;
Other than defining a Form_Closing event handler, this is the only structural change required to the form.
The Form_Closing event is straightforward.
private void From1_Closing ( object sender , FormClosingEventArgs e )
{
if (this.CausesValidation )
{ // There is no sense repeating this procedure if another routine already did it.
DisableValidation ( );
} // if (this.CausesValidation )
if ( _fExceptionIsFatal )
{ // Cancel False == Allow form to close.
e.Cancel = false;
} // if ( _fExceptionIsFatal )
} // From1_Closing
Though DisableValidation is implemented as a local method of the current form, the same thing could be accomplished by passing a Form reference into a library routine, since a Form is a Form, and its Controls collection is a Controls collection, period. Before long, I'll do so, along with implementing its inverse, to turn validation on again.
private void DisableValidation ( )
{
foreach ( Control ctrl in this.Controls )
{
ctrl.CausesValidation = false;
} // foreach ( Control ctrl in this.Controls )
this.CausesValidation = false;
} // DisableValidation
The fourth piece of the solution is equally straightforward; whenever you want to force the form to close, set _intValueAsInteger to TRUE before you call this.Close.
Add below code to your form. You can close the form even the children controls are validating.
protected override void WndProc(ref Message m)
{
if (m.Msg == 0x10) // The upper right "X" was clicked
{
this.ActiveControl = null;
this.AutoValidate = AutoValidate.Disable;
}
base.WndProc(ref m);
}
This question is pretty old but thought of adding the answer anyway:
In the form constructor:
this.FormClosing += Form1_FormClosing;
In the closing event handler (Make sure CausesValidation for the form is set to true to begin with. You could also check the textbox's CausesValidation property instead of the form's) :
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (this.CausesValidation)
{
DisableValidation();
this.Close();
}
}
In the DisableValidation method, disable validation for the textboxes and the form (I am using 2):
private void DisableValidation()
{
txtbox1.CausesValidation = false;
txtbox2.CausesValidation = false;
CausesValidation = false;
}
I do not understand why i did not get the help message after pressing the F1 key. When on windows form i got for instance one button and it has the focus the message is displayed as expected (after pressing F1) but when i got an empty form this is not happening. I suppose that an empty form will have by default focus set on it. ( i read that this event will be raised after pressing F1 for the control which got the focus)
Is this the right behavior, or i am missing something about the "HelpRequested" event on an empty form ? Is this the right way to raise the event based on focus or it could be configured to be raised also on another event (something like onMouseOver) ? May i create my own event and raise it ? (i do not want to add a special button only for help, for example press this button and display the help, help should be displayed only after F1 was pressed).
This is the code:
private void Form1_Load(object sender, EventArgs e)
{
Form1.ActiveForm.HelpRequested += new HelpEventHandler(helpReq);
//button1.HelpRequested += new HelpEventHandler(helpReq);
}
private void helpReq(object sender, HelpEventArgs hlpevent)
{
MessageBox.Show(((Control)sender).Text);
}
using Form1.ActiveForm, is not recommended. Change it to this
there is no Text property associated with Control. Do you mean Tag?
after performing the help event, you should set the HelpEventArgs.Handled to true
instead of using events, you can just override OnHelpRequested in your form.
I would do someething like this:
protected override void OnHelpRequested(object sender, HelpEventArgs e)
{
MessageBox.Show((Control) sender).Tag);
e.Handled = true;
base.OnHelpRequested(sender, e);
}
I am trying to make the save button visible when text is entered into the text box by using the following code:
if (tbName.TextModified == true)
{
btnCTimetablesOk.Visible = true;
}
else
{
btnCTimetablesOk.Visible = false;
}
but it gives error at tbname.textmodified
is there any other way to visible the button when we enter the text in text box
this is error i am getting "the event textbox.textmodified can only appear on the left hand side of += or -="
Try using the textbox's Enter and Leave events to show/hide your button:
private void textBox1_Enter(object sender, System.EventArgs e)
{
btnCTimetablesOk.Visible = true;
}
private void textBox1_Leave(object sender, System.EventArgs e)
{
btnCTimetablesOk.Visible = false;
}
Then modify your textbox to use these new methods.
If I'm reading your text correctly, you want the save button to be visible when the textbox has text in it and invisible when the text box is blank. If that's the case, you can use the Leave event (which occurs when the textbox loses focus) and a simple if statement:
private void textBox1_Leave(object sender, System.EventArgs e)
{
if(textBox1.Text != "")
btnCTimetablesOk.Visible = true;
else
btnCTimetablesOk.Visible = false;
}
You can also put this conditional block in any other methods kicked off by events that change the text of the box.
Also, you might want to consider using Enabled instead of Visible, it'll leave the button on the form but will gray out the text and clicking will do nothing.
I'm going to take a stab in the dark here and assume that the button is related to the textbox and you probably want someone to be able to type something in the textbox then click the button. You probably don't want the user to have to type something, then tab out or click somewhere else to make the button visible then click the button.
tbName_TextChanged(object sender, EventArgs e)
{
btnCTimetablesOk.Visible = !String.IsNullOrEmpty(tbName.Text)
}
Btw you're getting that error because TextModified isn't a boolean property, it's an event, like TextChanged or Leave or Enter. You can assign an event handler to it but you can't just check it like that.
As an aside I personally hate systems hungarian for winforms controls. I'd much rather have a timetablesOkButton than a btnCTimeablesOK button. That way if you also have a timetablesNameTextBox you can see at a glance that the button and the textbox match. Of course it may not be up to you.
I currently determine what page of a tabcontrol was clicked on via the SelectedIndexChanged event.
I would like to detect before the selected index actually changes, for validation purposes. For example, a user clicks a tab page other than the one they are viewing. A dialog is presented if form data is unsaved and asks if it's ok to proceed. If the user clicks no, the user should remain on the current tab.
Currently I have to remember the previous tab page and switch back to it after an answer of 'no.'
I considered MouseDown (and the assorted calculation logic), but I doubt that's the best way.
Add such an event to the tabControl when form_load:
tabControl1.Selecting += new TabControlCancelEventHandler(tabControl1_Selecting);
void tabControl1_Selecting(object sender, TabControlCancelEventArgs e)
{
TabPage current = (sender as TabControl).SelectedTab;
// Validate the current page. To cancel the select, use:
e.Cancel = true;
}
I've actually tried all of the events including the suggestions here and none of the mentioned events occur at the right time to actually trap moving from the tab.
Even the tab page validation event fires when entering the tab rather than leaving it - either that or there's something peculiar going on with my machine or .NET 4. On the other hand, in .NET 4 there is the Deselecting event which fires at the right time for my purposes.
private void tab_Deselecting(object sender, TabControlCancelEventArgs e)
{
}
The TabControl has a collection of TabPages, each of which you can enforce validation on, e.g.:
public partial class MyForm : Form
{
public MyForm()
{
InitializeComponent();
foreach (var page in _tabControl.TabPages.Cast<TabPage>())
{
page.CausesValidation = true;
page.Validating += new CancelEventHandler(OnTabPageValidating);
}
}
void OnTabPageValidating(object sender, CancelEventArgs e)
{
TabPage page = sender as TabPage;
if (page == null)
return;
if (/* some validation fails */)
e.Cancel = true;
}
}