I have created a program that contains (for now) 2 forms.
In the first form I am asking the user for a file. After the user has selected a file, another form is called followed by closing of the current form.
An if statement indicates if the user has inserted a file when the Open File button is pressed, and if not, the second form will not be loaded.
The problem is that if the user clicks the Close button on the first form (the current one), the form closes and the next one is called.
The options of the next form are based on the user's input in the first form (where the user is asked to select a file), so if the second form is called when the user cancels the first form, it will create problems for methods in the second form.
Any ideas about how to handle the Close Button?
If you want to prevent closing the form you can handle the event
bool cancel = true;
protected override void OnFormClosing(FormClosingEventArgs e)
{
e.Cancel = cancel;
base.OnFormClosing(e);
}
Remember to change cancel to false when it's done to close the form.
There is an event named "FormClosing" on forms.
A quick sample:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("Are you sure you want to quit?", MessageBoxButtons.YesNo) == DialogResult.No)
{
e.Cancel = true;
}
}
I am assuming that you have an OpenfileDialog (to allow the user to select a file),and a button probably named Open File to pass the filename to next form.If this is the case,then you can try to to disable the open button if no file has been selected.
Consider the code below as the function where all logic takes place;
private void BrowseFile()
{
//dlgopenfile is the name of Openfiledialog that allows the user to browse for a file.
//string filename is the name of selected file if any.
//Form2 is the next form.
try
{
switch (dlgopenfile.ShowDialog())
{
case DialogResult.OK://If Ok(Yes) button is pressed on Openfiledialog.
filename = dlgopenfile.FileName;
break;
case DialogResult.Cancel://If Cancel button is pressed on Openfiledialog.
filename = "";
break;
}
if (filename.Length >= 1)
{
if (File.Exists(filename) == true)
{
ButtonOpenFile.Enabled = true;
}
else
{
ButtonOpenFile.Enabled = false;
throw new FileNotFoundException("The file you selected does not exist.");
}
}
}
catch (FileNotFoundException ex)
{
MessageBox.Show(ex.Message, "Form1", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
The next function occurs if user tries to close the form in mid session.
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
switch (MessageBox.Show("Do you want to exit ?", "Form1", MessageBoxButtons.YesNo, MessageBoxIcon.Asterisk))
{
case DialogResult.Yes:
this.Close();
break;
case DialogResult.No:
e.Cancel = true;
break;
}
}
catch (Exception)
{
//Exception handling code goes here.
}
}
Finally the function below calls Form2's constructor with the selected file as argument.
private void ButtonOpenFile_Click(object sender, EventArgs e)
{
//This Button is enabled only if the file has been selected and if its exists.
Form2 form2 = new Form2(filename);//filename is the name of selected file,as decided in function BrowseFile().
this.Close();//Close Form1.
form2.ShowDialog();//Show Form2 as modal dialog.
}
Hope it would help you achieve what you need.Anything more,please let me know.
Proposally you start you form with form.ShowDialog(), which returns DialogResult. You should check whether it is DialogResult.Ok or whether form.DialogResult != DialogResult.None. In the form, if the user inserts the file you can set the form.DialogResult explicitely to DialogResult.Ok
Just you can handle the close event with your own logic
private void Form1_FormClosing_1(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show(text:"Are you sure you want to quit?",caption:string.Empty,buttons: MessageBoxButtons.YesNo) == DialogResult.No)
{
e.Cancel = true;
}
}
Related
I'm writing a WinForm desktop application. In the main form, the user clicks on a button which calls another form for the user to submit data to. At the end of this submission process, the user clicks on a "Save" menu item to close the subform.
This is the code for the subform calling:
private void btnSubmit_Click(object sender, EventArgs e)
{
// code for setting myFormArgs
myForm form = new myForm(myFormArgs);
form.ShowDialog();
// the user clicked "Yes" on a "Confirm" MessageBox
if (form.DialogResult == DialogResult.Yes)
{
// code for saving data
form.Dispose();
}
}
and this is the code for the "Save" menu item in the subform:
private void menuSave_Click(object sender, EventArgs e)
{
string message, title;
MessageBoxIcon icon;
MessageBoxButtons buttons;
if(DataSubmitted)
{
if(ValidData)
{
message = "Confirm?";
title = "Select an action";
icon = MessageBoxIcon.Information;
buttons = MessageBoxButtons.YesNo;
}
else
{
message = "Incomplete data";
title = "Error";
icon = MessageBoxIcon.Error;
buttons = MessageBoxButtons.OK;
}
}
else
{
message = "No data submitted";
title = "Error";
icon = MessageBoxIcon.Error;
buttons = MessageBoxButtons.OK;
}
this.DialogResult = MessageBox.Show(message, title, buttons, icon);
if (this.DialogResult == DialogResult.Yes) this.Close();
else this.OnFormClosing(new FormClosingEventArgs(CloseReason.None, true));
}
The problem is that the code will always get back to the calling method, thus closing (maybe just hiding?) the sub-form, even if the this.Close() method isn't called.
Thanks in advance.
you should not make a new event instance, those are things you would want to avoid
instead try:
DialogResult dialogResult = MessageBox.Show("Sure", "Some Title",
MessageBoxButtons.YesNo);
if(dialogResult == DialogResult.Yes)
{
Close();
}
Events are supposed to occur automatically, so 'OnFormClosing' will raise when the form will close.
also i recommend to use this.Close instead of Dispose
Form.Close() sends the proper Windows messages to shut down the win32 window. During that process, if the form was not shown modally, Dispose is called on the form. Disposing the form frees up the unmanaged resources that the form is holding onto.
for more organized code,
try making an instance of the form from the main form
and handle the dialog result like this:
using (SubForm form = new SubForm())
{
DialogResult dr = form.ShowDialog();
if(dr == DialogResult.Yes)
{
string studdToSave= form.StuffToSave;
SaveToFile(studdToSave);
}
}
I find it strange that you want to close the form when the user just wants to save the data. :)
Save should not close your form.
When you close the form, you should verify if there are unsaved changes.
If there are, ask the user the question if he wants to save his changes before closing and offer him the options Yes, No and Cancel, where Cancel means 'cancel closing the form'.
Depending on wether the user clicked Yes or No, you should or shouldn't save the changes.
If the user clicked cancel, you should cancel closing the form by having an event for the FormClosing event. This event allows you to cancel closing the form.
private void btnClose_Click(object sender, EventArgs e)
{
if (unsavedChanges)
{
var result = MessageBox.Show("Save changes?", "unsaved changes", MessageBoxButtons.YesNoCancel);
if (result == DialogResult.Yes)
{
SaveChanges();
}
if (result == DialogResult.Cancel)
{
cancelClose = true;
}
this.Close();
}
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = cancelClose;
cancelClose = false;
}
The code above is usefull when 'Form2' is not a modal form.
If you want Form2 to be shown modal, the code above will work as well. However, you can also use the DialogResult proprety of the Form in that case:
private void btnClose_Click(object sender, EventArgs e)
{
if (unsavedChanges)
{
var result = MessageBox.Show("Save changes?", "unsaved changes", MessageBoxButtons.YesNoCancel);
if (result == DialogResult.Yes)
{
SaveChanges();
}
if (result == DialogResult.Cancel)
{
result = DialogResult.None;
}
this.DialogResult = result;
}
}
I have a WinForms application that checks for pending changes whenever the user hits the cancel button. If there are pending changes, I prompt the user to see if they are sure they wish to cancel. If they do, I close the form. If not, I just return. However, the form is closing anyways. After some debugging, I realized it was because this particular button is set to the form's CancelButton, so clicking it caused the form to close. To verify, I removed the CancelButton property, but the behavior persisted.
How can I prevent this automatic closing? Here is my event handler code:
private void closeButton_Click(object sender, EventArgs e)
{
DialogResult dr = DialogResult.Yes;
if (changesMade)
{
dr = MessageBoxEx.Show(this, "Are you sure you wish to disregard the changes made?", "Changes Made", MessageBoxButtons.YesNo);
}
if (dr == DialogResult.Yes)
{
Close();
}
else
{
//TODO:
}
}
In the above code, the form should only close if there are no changes made, or if the user chose to disregard them. I made changes, and clicked 'No' to the DialogBox, but the form still closed. With and without the button set as the form's CancelButton.
Just set the property DialogResult of the form to the enum DialogResult.None
....
if (dr == DialogResult.Yes)
{
Close();
}
else
{
this.DialogResult = DialogResult.None;
}
or simply:
if (dr != DialogResult.Yes)
this.DialogResult = DialogResult.None;
The form closes automatically because the property DialogResult of the button is not set to DialogResult.None in the Forms Designer. In this scenario, the WinForms engine takes that value and assign it to the DialogResult property of the whole form causing it to automatically close. This is usually used in the calling code of the form to distinguish between a Confirm and a Cancel button
In the example below suppose that on the frmCustomers there are two buttons, one with the DialogResult property set to DialogResult.OK and another set to DialogResult.Cancel. Now if the user hits the OK button you know, in the calling code what to do with the inputs for your new customer
using(frmCustomers f = new frmCustomers())
{
if(f.ShowDialog() == DialogResult.OK)
{
// Execute code to save a customer
}
}
Following up on my comment, this is what I do for an internal tool I wrote recently:
private void Form_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = !PromptUnsavedChanges();
}
private bool PromptUnsavedChanges()
{
if (HasFormChanged()) //checks if form is different from the DB
{
DialogResult dr = MessageBox.Show("You have unsaved changes. Would you like to save them?", "Unsaved Changes", MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
if (dr == System.Windows.Forms.DialogResult.Yes)
tsmiSave_Click(null, null); // Saves the data
else if (dr == System.Windows.Forms.DialogResult.Cancel)
return false; // Cancel the closure of the form, but don't save either
}
return true; // Close the form
}
The logic could probably cleaned up from a readability point of view, now that I'm looking at it months later. But it certainly works.
With this you simply just call this.Close(); in your button click event. Then that event is what handles the prompting and decides if it should actually close or not.
I'm trying to manipulate a PictureBox(pBATalk) to show whenever I close a form(PAInput). So basically I want to show a picture, whenever the 2nd form is closed.
2nd Form
public void PAInput_FormClosing(object sender, FormClosingEventArgs e)
{
this.Hide();
fPAMain.PATalkActive(false);
e.Cancel = true;
}
MainForm:
public void PATalkActive(bool active)
{
//MessageBox.Show("");
if (active == true)
{
pBPATalk.Hide();
}
if (active == false)
{
pBPATalk.Show();
}
}
Whenever I close PAInput it will trigger PATalkActive, but will only fire the MessageBox.Show(""); and not the pBATalk.Hide(); or pBATalk.Show();
Well, I'm not so sure about what you are trying to accomplish here but first of all you're keeping PAInput open, with this line e.Cancel = true . Besides that, MessageBox.Show(""); will open a modal window displaying a text, until it is closed the rest of the method won't run.
I have a form on which there is a LogOutEvent and a form closing event.
Here is the code,
private void btnLogOut_Click(object sender, EventArgs e)
{
DialogResult yesNo = MessageBox.Show(this, "Are you sure you want to Log Off?", "Log Off", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
if (yesNo == DialogResult.Yes)
{
new LoginForm();
this.Close();
string tst2 = Logout(AgentId, AgentPwd, ExtensionId);
if (tst2 == "TCF000")
MessageBox.Show(" Logout Success");
else
MessageBox.Show("Logout Failed");
}
}
And a Form Closing Event
private void MainGUI_FormClosing(Object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
DialogResult yesNo = MessageBox.Show(this, "Are you sure you want to Log Off?", "Log Off", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button1);
if (yesNo == DialogResult.Yes)
{
Application.Exit();
}
else
{
e.Cancel = true;
}
}
}
My Problem is when i click on the LogOut button its calling the form closing event. Can anybody advice a better code for this?
When i click on close 'X' it should close the application and when i click on LogOut it should close the current window and go to the login form.
I'm sure that there is a better solution, but this does work:
private bool loggingOut;
private void Form1_DoubleClick(object sender, EventArgs e)
{
this.loggingOut = true;
this.Close();
// This is optional as we are closing the form anyway
this.loggingOut = false;
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing && !loggingOut)
{
// Handle form closing here
}
}
This allows your form closing event handler to identify if another method is invoking the form close, and skip the normal handling if it is.
Alternatively you could just Hide the form instead, and re-use the same form instance the next time the user logs in.
well... yes! the form is closing; why wouldn't it fire the event?
If the CloseReason isn't helping, then just throw a bool field onto the form that you set to true when you click logout; and check that field in the closing event.
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.