I have a form which I use as a modal dialog box for data entry. When the user clicks on the OK button on the form, I want the button handler to perform data validations and if there is any error the form should reload/redisplay itself instead of returning to the caller. Is this possible?
Caller code:
DatasetProperties propsWindow = new DatasetProperties();
if (propsWindows.ShowDialog() == DialogResult.Cancel)
return;
// Do other stuffs here
Form code:
public partial class DatasetProperties : Form
{
// Constructor here
// OK button handler
private void btnOK_Click(object sender, EventArgs e)
{
// Do data validations here
if (errorsFound)
{
// How to reload/redisplay the form without return to caller?????
}
}
}
Thanks for any help,
Don't let the user close the form without validation.
Use the FormClosing event. Here's an example. In lieu of the messageBox, include your validation code. If it doesn't validate, e.cancel = true.
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("Are you sure you want to cancel without saving any changes?", "Confirm Cancel", MessageBoxButtons.YesNo) != DialogResult.Yes)
e.Cancel = true;
}
You can set the Form.DialogResult inside your DatasetProperties.btnOK_Click method to DialogResult.None, this way your DatasetProperties form will not return to the caller Form ('close').
// OK button handler
private void btnOK_Click(object sender, EventArgs e)
{
// Do data validations here
if (errorsFound)
{
this.DialogResult = System.Windows.Forms.DialogResult.None;
// How to reload/redisplay the form without return to caller?????
}
}
This way you can 'stay' in your DatasetProperties form as long as you have errors.
From the msdn, when the DialogResult Enumeration is set to None Nothing is returned from the dialog box. This means that the modal dialog continues running.
as user1646737 mentioned you can use FormClosing event like this:
private void btnOK_Click(object sender, EventArgs e)
{
// Do data validations here
Close();
}
Event:
private void DatasetProperties_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = errorsFound;
}
Related
I have a Log In form and I need to know if user pressed the X button on form or the button that takes him to the new form. If user closed the program with Alt+F4 or X button the program must be closed.
I was trying with FormClosing event to check whether user pressed X or login.
private void LogIn_FormClosing(object sender, FormClosingEventArgs e)
{
if (string.Equals((sender as Button).Name, #"loginButton"))
{
//some code
}
else
{
Close();
}
}
The FormClosing event handler receives a FormClosingEventArgs argument that contains the property CloseReason, but in your context this is not enough.
Indeed, in both cases (ALT+F4/X-Click or ButtonClick) the argument will contain a CloseReason equal to UserClosing.
I suggest you a simple workaround. In your button click handler (where you should call the close action on the form, not on the formclosing event handler itself), add something to the Tag property of the form like so:
private void Button1_Click(object sender, EventArgs e)
{
this.Tag = "ClosedByUser";
this.Close();
}
now in the FormClosing event handler is simple to check this property
private void LogIn_FormClosing(object sender, FormClosingEventArgs e)
{
if (this.Tag != null)
{
// Button clicked
}
else
{
// other reasons
// Dp not call Close here, you are already closing
// if you don't set e.Cancel = true;
}
}
I am learning about Forms and somehow can't figure out what's the problem with this code that when I want to press either button with Dialog.Result.Yes or button with Dialog.Result.No in Form2 to keep the Form2 open it anyway closes after clicking on one of them.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_MouseClick(object sender, MouseEventArgs e)
{
Formular2 Form2 = new Formular2();
Form2.ShowDialog();
if (Form2.DialogResult == DialogResult.Yes)
{
this.DialogResult = DialogResult.None;
}
else if (Form2.DialogResult == DialogResult.No)
{
DialogResult = DialogResult.None;
}
}
}
Thanks for any advice
If you want to keep the Form2 open, you need to set the DialogResult property of Form2, not the DialogResult property of Form1.
You need to move this logic in the button on Form2 that close the Form2
So, suppose to have a button on Formular form class named buttonOK and its property DialogResult is set to DialogResult.OK.
Then in that class code you write the event handler for the button click event (not the MouseClick event)
private void buttonOK_Click(object sender, MouseEventArgs e)
{
// Perform some logic to validate the inputs and if something is wrong return false
if(SomeLogicToAcceptTheForm() == false)
{
// Inform the user of the error
MessageBox.Show("Your input is not valid");
// Stop the closing process of this Formular instance
this.DialogResult = DialogResult.None;
}
// If your logic accepts the input, then the code continue at this point
// This will cause the form to exit from the ShowDialog call
// and you can read the current form DialogResult value.
}
EDIT
To better understand this flow you should consider that, BEFORE calling the event handler for the button click event, the forms engine sets the Form's DialogResult property from the value present in the button's DialogResult property. So, if your validation turns out to be correct you don't need to do anything and the form closes returning DialogResult.OK (or whatever you have put in the Button's DialogResult property).
The act of setting a DialogResult will cause the Form to close returning that result to the Form that created the instance, that way it can check the result and take the appropriate action. In your case since you want to keep the second form open you either need to not assign the DialogResult.No to the button and do like Steve suggests or you can intercept the Form's FormClosing event, test for the DialogResult if DialogResult.No set to None and cancel the Closing of the Form.
Though I would suggest not using a DialogResult if you are wanting to keep the Form Open.
public Form2()
{
InitializeComponent();
}
private void button2_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.No;
}
private void button1_Click(object sender, EventArgs e)
{
DialogResult = DialogResult.Yes;
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
if (this.DialogResult == DialogResult.No)
{
DialogResult = DialogResult.None;
e.Cancel = true;
}
}
In the Form2 pick control for assigning respective dialog result.
Same DialogResult will be produced by the Form2 control if you click on it.
Example in Form2:
button1.DialogResult = DialogResult.Yes;
button2.DialogResult = DialogResult.No;
Now pressing any of these buttons should close the Form2.
If you want to restrict closing on button1 and button2. Following changes in the Click event are required:
private void button1_Click(object sender, EventArgs e)
{
this.DialogResult = DialogResult.None;
}
Form1:
In result you could see what is result, by looking into Form2.DialogResult. You can do this as you get results from Form2 dialog:
Formular2 Form2 = new Formular2();
Form2.ShowDialog();
if (Form2.DialogResult == DialogResult.Yes)
{
//
}
else if (Form2.DialogResult == DialogResult.No)
{
//
}
On any windows form displayed as modal (using ShowDialog()), the act of setting DialogResult will cause to hide the modal form and return control to calling code. Read Remarks from this page of MSDN
If you wish to show your form again, you can do the following:
private void button1_MouseClick(object sender, MouseEventArgs e)
{
Formular2 Form2 = new Formular2();
Form2.ShowDialog();
if (Form2.DialogResult == DialogResult.Yes)
{
Form2.DialogResult = DialogResult.None;
}
else if (Form2.DialogResult == DialogResult.No)
{
Form2.DialogResult = DialogResult.None;
}
Form2.Show(); // or Form2.ShowDialog()
}
I have a form which contains a close button (there are many control in the form, but I am concerning about the close event) and a save button.
If a form have value in certain text box (say TextBox1),
Then I want to validate that the save button is clicked before closing the form (whether close button or the 'X' button at top is pressed).
But if there is no value in that text box or the form is just initialized and user just want to close the form, it simply closes the form. How to perform this validation.
I would follow the pattern of 99% of windows applications: allow to close a window, but ask to save changes if there are any. Here is a simple implementation of that pattern:
private bool _hasChanges;
private void textBox1_TextChanged(object sender, EventArgs e)
{
this._hasChanges = true;
}
private void form_FormClosing(object sender, FormClosingEventArgs e)
{
if (this._hasChanges)
{
var dialogResult = MessageBox.Show("Save changes?", "Confirm", MessageBoxButtons.YesNoCancel);
switch (dialogResult)
{
case DialogResult.Yes:
this.Save();
break;
case DialogResult.No:
this._hasChanges = false;
break;
}
e.Cancel = this._hasChanges;
}
}
private void Save()
{
// Save
this._hasChanges = false;
}
private void buttonSave_Click(object sender, EventArgs e)
{
this.Save();
}
private void buttonOk_Click(object sender, EventArgs e)
{
this.Close();
}
private void buttonCancel_Click(object sender, EventArgs e)
{
this._hasChanges = false;
this.Close();
}
The pivotal part is the boolean _hasChanges. If there are many controls that can cause changes this can be real pain. An alternative could be to use databinding to a class that implements INotifyPropertyChanged and subscribe to its PropertyChanged event.
Tie into the Closing Event and use your EventHandler to validate that textbox. Keep in mind that Closing occurs at the time the form is closing and (if memory servers correctly) there is a property on the eventarg that will let you cancel closing of the form. This event is raised regardless of how the request is executed.
I have the following code:
private void form1_closing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
this.Hide();
}
I want a button that closes the form, without triggering this event. How do I do this?
The code for the button:
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
Application.Exit();
}
I want the above button to close the form and not hide it.
//unsubscribe the mean "don't let me close" handler
this.FormClosing -= form1_closing;
//close form
this.Close();
Another option would be to make a boolean field "shouldIReallyClose". Default it to false. When you really want to close the form set it to true. Change the event handler to check that boolean before canceling the event.
protected override void OnFormClosing(FormClosingEventArgs e)
{
if(!boolTrackingButtonPressed)
{
base.OnFormClosing(e);
}
}
I have a dialog that I show with <class>.ShowDialog(). It has an OK button and a Cancel button; the OK button also has an event handler.
I want to do some input validation in the event handler and, if it fails, notify the user with a message box and prevent the dialog from closing. I don't know how to do the last part (preventing the close).
You can cancel closing by setting the Form's DialogResult to DialogResult.None.
An example where button1 is the AcceptButton:
private void button1_Click(object sender, EventArgs e) {
if (!validate())
this.DialogResult = DialogResult.None;
}
When the user clicks button1 and the validate method returns false, the form will not be closed.
Given that you've specified you want a pop error dialog, one way of doing this is to move your validation into a OnClosing event handler. In this example the form close is a aborted if the user answers yes to the question in the dialog.
private void Form1_Closing(object sender, System.ComponentModel.CancelEventArgs e)
{
// Determine if text has changed in the textbox by comparing to original text.
if (textBox1.Text != strMyOriginalText)
{
// Display a MsgBox asking the user to save changes or abort.
if(MessageBox.Show("Do you want to save changes to your text?", "My Application",
MessageBoxButtons.YesNo) == DialogResult.Yes)
{
// Cancel the Closing event from closing the form.
e.Cancel = true;
// Call method to save file...
}
}
}
By setting e.Cancel = true you will prevent the form from closing.
However, it would be a better design/user experience to display the validation errors inline (via highlighting the offending fields in some way, displaying tooltips, etc.) and prevent the user from selecting the OK button in the first place.
Don't use the FormClosing event for this, you'll want to allow the user to dismiss the dialog with either Cancel or clicking the X. Simply implement the OK button's Click event handler and don't close until you are happy:
private void btnOk_Click(object sender, EventArgs e) {
if (ValidateControls())
this.DialogResult = DialogResult.OK;
}
Where "ValidateControls" is your validation logic. Return false if there's something wrong.
You can catch FormClosing an there force the form to remain opened.
use the Cancel property of the event argument object for that.
e.Cancel = true;
and it should stop your form from closing.
This doesn't directly answer your question (other already have), but from a usability point of view, I would prefer the offending button be disabled while the input is not valid.
Use this code:
private void btnOk_Click(object sender, EventArgs e) {
if (ValidateControls())
this.DialogResult = DialogResult.OK;
}
The problem of it is that the user has to clic two times the buttons for closing the forms;
Just add one line in the event function
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e)
{
this->DialogResult = System::Windows::Forms::DialogResult::None;
}
I wish I had time to find a better example, but you would be much better off using the existing windows forms validation techniques to do this.
http://msdn.microsoft.com/en-us/library/ms229603.aspx
void SaveInfo()
{
blnCanCloseForm = false;
Vosol[] vs = getAdd2DBVosol();
if (DGError.RowCount > 0)
return;
Thread myThread = new Thread(() =>
{
this.Invoke((MethodInvoker)delegate {
picLoad.Visible = true;
lblProcces.Text = "Saving ...";
});
int intError = setAdd2DBVsosol(vs);
Action action = (() =>
{
if (intError > 0)
{
objVosolError = objVosolError.Where(c => c != null).ToArray();
DGError.DataSource = objVosolError;// dtErrorDup.DefaultView;
DGError.Refresh();
DGError.Show();
lblMSG.Text = "Check Errors...";
}
else
{
MessageBox.Show("Saved All Records...");
blnCanCloseForm = true;
this.DialogResult = DialogResult.OK;
this.Close();
}
});
this.Invoke((MethodInvoker)delegate {
picLoad.Visible = false;
lblProcces.Text = "";
});
this.BeginInvoke(action);
});
myThread.Start();
}
void frmExcellImportInfo_FormClosing(object s, FormClosingEventArgs e)
{
if (!blnCanCloseForm)
e.Cancel = true;
}
You can probably check the form before the users hits the OK button. If that's not an option, then open a message box saying something is wrong and re-open the form with the previous state.