Why is my FormClosing event handler throwing a stack overflow exception? - c#

I want to validate input on two textboxes on my form if the user clicks the close/"red X" button. I assigned an event handler to the FormClosing property of the Form, but when I click it, the program goes into an infinite loop and then throws the stack overflow exception. Here is my code:
private bool _Cancel(object sender, EventArgs e)
{
if (((this.textboxFirstName.Text != null) && (this.textboxFirstName.Text != string.Empty))
|| ((this.textboxLastName.Text != null) && (this.textboxLastName.Text != string.Empty)))
{
DialogResult pResult = MessageBox.Show("Do you want to cancel adding this driver?", "Warning", MessageBoxButtons.YesNo);
if (pResult == DialogResult.Yes)
{
this.Close();
return true;
}
else return false;
}
else
{
this.Close();
return true;
}
}
private void AddDriver_Window_FormClosing(object sender, FormClosingEventArgs e)
{
if (!this._Cancel(sender, e))
e.Cancel = true;
}
What am I doing wrong? As far as I know, if I set the Cancel property to true the form should cancel closing. MS' documentation is no help...
EDIT: Is it bad practice to piggyback onto the EventArgs e passed in the call to this._Cancel and send a e.CloseReason that I specify? The reason why I originally had the this.Close() is because this handler was originally written for a cancel button on the form (different from the close button). I wanted to reuse the code, so I was thinking of checking this parameter in the _Cancel method to determine if this.Close() should be called.
EDIT 2: Nevermind figure I can just check if the e.CloseReason is "UserClosing"

Ali why are you call
if (pResult == DialogResult.Yes)
{
this.Close();
return true;
}
else return false;
in case the dialog box = vbyes return true or false as per your need in example
private bool _Cancel(object sender, EventArgs e)
{
if (((this.textboxFirstName.Text != null) && (this.textboxFirstName.Text != string.Empty))
|| ((this.textboxLastName.Text != null) && (this.textboxLastName.Text != string.Empty)))
{
DialogResult pResult = MessageBox.Show("Do you want to cancel adding this driver?", "Warning", MessageBoxButtons.YesNo);
if (pResult == DialogResult.Yes)
{
//avoid => this.Close();
return true;
}
else return false;
}
else
{
// avoid => this.Close();
return true;
}
}

Related

C# Winform TreeView BeforeSelect event firing twice

I am using the before select event on a tree view to trigger a "Save your changes" cycle.
Everything works fine but I recently added in some validation of a few fields and a need to be able to cancel the event. It appears the e.Cancel = true in the below code causes the BeforeSelect event to fire twice.
private void TvEmps_BeforeSelect(object sender, TreeViewCancelEventArgs e) {
if (dgchanged) {
DialogResult dialogResult =
MessageBox.Show("Save your changes?", "Confirmation", MessageBoxButtons.YesNo);
if (dialogResult == DialogResult.Yes) {
BtnSaveAll_Click(sender, e);
if (!isvalid) {
e.Cancel = true; // this causes the beforeselect event to fire twice
return;
}
}
}
}
I have tried the following but I am still getting double prompted:
{
if (dialogShowing) return;
if (dgchanged == true)
{
dialogShowing = true;
DialogResult dialogResult = MessageBox.Show("Save your changes?", "Confirmation", MessageBoxButtons.YesNo);
dialogShowing = false;
if (dialogResult == DialogResult.Yes)
{
BtnSaveAll_Click(sender, e);
e.Cancel = !isvalid;
}
}
}```
As commented, the DialogBox is the cause of the BeforeSelect firing again, because it causes the TreeView control to regain the focus.
To work around the issue, try using a variable to determine if the dialog should be raised:
private bool dialogShowing = false;
private void TreeView1_BeforeSelect(object sender, TreeViewCancelEventArgs e)
{
if (dialogShowing) return;
dialogShowing = true;
DialogResult dr = MessageBox.Show("Confirm?", "Warning", MessageBoxButtons.YesNo);
dialogShowing = false;
if (dr == DialogResult.Yes)
{
// call save
} else
{
e.Cancel = true;
}
}

WinForms - Alert When User Leaves Page Without Saving [duplicate]

How can I prevent window closing by showing a MessageBox? (Technology:WinForms with C#)
When the close event occurs I want the following code to be run:
private void addFile_FormClosing( object sender, FormClosingEventArgs e ) {
var closeMsg = MessageBox.Show( "Do you really want to close?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Question );
if (closeMsg == DialogResult.Yes) {
//close addFile form
} else {
//ignore closing event
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e) {
var window = MessageBox.Show(
"Close the window?",
"Are you sure?",
MessageBoxButtons.YesNo);
e.Cancel = (window == DialogResult.No);
}
Catch FormClosing event and set e.Cancel = true
private void AdminFrame_FormClosing(object sender, FormClosingEventArgs e)
{
var res = MessageBox.Show(this, "You really want to quit?", "Exit",
MessageBoxButtons.YesNo, MessageBoxIcon.Warning, MessageBoxDefaultButton.Button2);
if (res != DialogResult.Yes)
{
e.Cancel = true;
return;
}
}
A special twist might be to always prevent just the user closing the form:
private void Frm_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = (e.CloseReason == CloseReason.UserClosing);
// disable user closing the form, but no one else
}
Within your OnFormClosing event you can show the dialog and if answer is false (to not show) then set the Cancel property of the EventArgs to true.
For prevent or block the form closing in particular situation you can use this strategy:
private void MyForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (FLAG_CONDITION == true)
{
MessageBox.Show("To exit save the change!!");
e.Cancel = true;
}
}
Straight from MSDN:
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...
}
}
}
In your case you don't need to do anything to explicitly close the form. Unless you cancel it it will close automatically, so your code would be:
private void addFile_FormClosing( object sender, FormClosingEventArgs e ) {
var closeMsg = MessageBox.Show( "Do you really want to close?", "Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Question );
if (closeMsg == DialogResult.Yes) {
// do nothing
} else {
e.Cancel = true;
}
}
You can run any code you want when closing the form then, hide the form instead of closing it to prevent it from being disposed
yourFormName.FormClosing += (s, e) =>
{
// any code you want
yourFormName.Hide(); // this hides the form
e.Cancel = true; // this cancels the close event, you can put any boolean exprission
};

How do I prevent CheckChanged to fire after setting Checked in that event?

I have this code in my CheckedChanged event handler:
private void cbLoadStock_CheckedChanged(object sender, EventArgs e) {
if (cbLoadStock.Checked == false &&
MessageBox.Show("Are you sure you want to do that?",
"Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes) {
cbLoadStock.Checked = true;
} else {
cbLoadStock.Checked = false;
}
}
But, when I click "Yes", it sets Checked to true causing the handler to be called again.
How can I make the checkbox to just be set checked?
As I mentioned in my comment, this should do the work:
private void cbLoadStock_CheckedChanged(object sender, EventArgs e) {
cbLoadStock.CheckedChanged -= cbLoadStock_CheckedChanged;
if (cbLoadStock.Checked == false &&
MessageBox.Show("Are you sure you want to do that?",
"Warning", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation) == DialogResult.Yes) {
cbLoadStock.Checked = true;
} else {
cbLoadStock.Checked = false;
}
cbLoadStock.CheckedChanged += cbLoadStock_CheckedChanged;
}

Built in MessageBox Dialog Closing custom Form.ShowDialog()

Okay Problem As Follows:
I call up a custom form as follows:
SomeCustomForm _newForm = new SomeCustomForm();
_newForm.ShowDialog();
//**SOME OTHER CODE**
Now lets say we have some custom event (Mine is on a DataGridView DoubleClick):
private void dgvSomeGrid_DoubleClick(object sender, EventArgs e)
{
string name = dgvSomeGrid.CurrentRow.Cells[5].Value.ToString();
DialogResult = MessageBox.Show(name, "Select this Merkmal?", MessageBoxButtons.YesNo);
if (DialogResult == DialogResult.Yes)
{
_someID = Convert.ToInt32(dgvMSomeGrid.CurrentRow.Cells[0].Value.ToString());
this.Close();
}
else if (DialogResult == DialogResult.No)
{
return;
}
}
The dialog works fine in that the no and yes buttons behave as expected. My problem though is that irrespective of which button is clicked, the code jumps back to //**SOMEOTHERCODE. So in effect, the _newForm is just closed.
I obviously don't want this to happen as I am not done on the other form yet if the "No" button is clicked.
Any help?
EDIT:
My apologies - for the sake of clarity. The grid mentioned above is on the _newForm. And the dialog is called from the _newForm.
This closes unexpectedly.
don't use DialogResult property of form for comparison. Set it only on successful close
private void dgvSomeGrid_DoubleClick(object sender, EventArgs e)
{
string name = dgvSomeGrid.CurrentRow.Cells[5].Value.ToString();
var result = MessageBox.Show(name, "Select this Merkmal?", MessageBoxButtons.YesNo);
if (result == DialogResult.Yes)
{
_someID = Convert.ToInt32(dgvMSomeGrid.CurrentRow.Cells[0].Value.ToString());
this.DialogResult = DialogResult.Yes;
this.Close();
}
}
somewhere in code type static bool formCloseFlag = false;
Let's shorten your event handler code a bit:
private void dgvSomeGrid_DoubleClick(object sender, EventArgs e)
{
string name = dgvSomeGrid.CurrentRow.Cells[5].Value.ToString();
DialogResult = MessageBox.Show(name, "Select this Merkmal?", MessageBoxButtons.YesNo);
if (DialogResult == DialogResult.Yes)
{
_someID = Convert.ToInt32(dgvMSomeGrid.CurrentRow.Cells[0].Value.ToString());
formCloseFlag = true;
}
return;
}
then change your code like this :
SomeCustomForm _newForm = new SomeCustomForm();
_newForm.ShowDialog();
//**SOME OTHER CODE**
if(formCloseFlag) { _newForm.Close(); formCloseFlag = false; }
//**SOME OTHER CODE**
A workaround on this is to add a handler for the FormClosing event of your form, so you can cancel it there.
[edit]
After some experimenting, it seems that the bug is somewhat detectable by checking FormClosingEventArgs.CloseReason. This is normally "UserClosing" on normal close (even programmatically with calling this.Close()), but with this bug it's set to "None", a value I would assume is some kind of default that should normally never be used.
private void form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.None)
{
e.Cancel = true;
return;
}
// any other OnClose code you may wish to execute.
}

Form close event

I had an problem with my application closing in c#. When I hit the close button it display twice or more times the message box. What should I do?
private void home_FormClosed(object sender, FormClosedEventArgs e)
{
DialogResult dialog = MessageBox.Show("Are you sure you want to really exit ? ",
"Exit",
MessageBoxButtons.YesNo,
MessageBoxIcon.Question);
if (dialog == DialogResult.Yes)
{
System.Windows.Forms.Application.Exit();
}
else if (dialog == DialogResult.No)
{
this.Show();
}
}
Use Form1_FormClosing event and also don't use Application.Exit() like this:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
var x = MessageBox.Show("Are you sure you want to really exit ? ",
"Exit", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (x == DialogResult.No)
{
e.Cancel = true;
}
else
{
e.Cancel = false;
}
}
Or like this:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = MessageBox.Show("Are you sure you want to really exit ? ",
"Exit", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No;
}
you should use the Form.FormClosing event instead of the FormClosed event. in the arguments, you find a field e.Cancel. by setting this to false, you keep your form open
You can avoid the multiple prompts by checking to see if Application.Exit() has been called already from within the FormClosing event:
void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason != CloseReason.ApplicationExitCall)
{
DialogResult dialog = MessageBox.Show("Are you sure you want to really exit ? ", "Exit", MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dialog == DialogResult.Yes)
{
System.Windows.Forms.Application.Exit();
}
else if (dialog == DialogResult.No)
{
e.Cancel = true;
}
}
}
Use the form closing event instead.
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
var confirmation = MessageBox.Show("Sure to close form", "Confirm", MessageBoxButtons.YesNo);
if (confirmation == System.Windows.Forms.DialogResult.No)
{
e.Cancel = true; //Even cancelled, form will not get closed now
}
}

Categories

Resources