On the click of a button (that's in the main form), I show a (second) form that does some parsing (decompress, extract, get information, etc) of an archive file. After this process is done, I close the second (parsing) form and show another (third) form that contains the parsed information from the archive.
Click callback looks like this:
private void ParseInputBackupButton_Click(object sender, EventArgs e)
{
Form PBF = new ParseBackupForm();
Form CBF = new CreateBackupForm();
PBF.FormClosed += delegate
{
CBF.ShowDialog();
};
PBF.ShowDialog();
}
and the second form:
private void ParseBackupForm_Load(object sender, EventArgs e)
{
new Thread((ThreadStart)delegate
{
// parse and update form
this.Invoke((MethodInvoker)delegate
{
this.Close();
});
}).Start();
}
The problem is when the third form (CreateBackupForm) appears, the second form (ParseBackupForm) doesn't close. They both appear. If I don't show the third form, the second form closes.
What am I doing wrong?
As you are calling ShowDialog on both windows, couldn't you just call them one after the other?
i.e.
PBF.ShowDialog();
CBF.ShowDialog();
The second call will not be made until the PBG dialog has closed.
Edit: The reason why the second form doesn't close is that the you are subscribing to an event raised by the form as it closes, then within that delegate calling ShowDialog which blocks the form from actually closing.
As far as I can remember .ShowDialog() is a blocking method, so would stop the other form from completing its close method until that form is also closed?
Pretty sure you can use .Show() to just make a form visible without blocking?
You could BeginInvoke the call of CBF.ShowDialog();, thus not blocking the completion of the FormClosed callback method and the closing of the PBF form.
Related
I have a class with several functions, within all of these functions I have a try catch and in a catch I start a new form to show the error. Like this:
Program.erro = exception.ToString();
Error NewError = new Error();
Error.ShowDialog();
But I need to be able to close the current form FormUpdate as an example whenever I close the error form.
I've put this line of code in the error's FormClosed event:
UpdateOrca.Update.ActiveForm.Close();
"Update" is the open form that needs to be closed.
You could just make use of the using statement and then when your error dialog has been closed, the rest of the code will execute.
using (Error NewError = new Error())
{
NewError.ShowDialog()
}
this.close();
You can then remove the code that you have placed in NewError's closing event.
As you can see in that SO question creating close event of the child form in main form, and calling this.close() inside it will solve the problem.
You should pass the calling form instance to the dialog form. .NET allows you identify the owner form of the openning form.
For example; You can open a popup like;
Dialog frmDialog = new Dialog();
frmDialog.ShowDialog(this);
Then; in the popup form you can listen the form_closing event like;
private void Dialog_FormClosing(object sender, FormClosingEventArgs e)
{
if (this.Owner != null)
this.Owner.Close();
}
Hope it helps.
I'm using visual studio 2010
frmMain has a "Register" button which calls another form newReg
This is the code for the button in frmMain that calls the second form. The problem is that the MessageBox("So Far So Good") never gets called. The dialogResult doesnt seem to be recognized.
private void btnRegisterNew_Click(object sender, EventArgs e)
{
// newReg Constructor Call
newReg = new frmRegisterNew();
// show form
newReg.Show();
if (newReg.DialogResult.Equals(DialogResult.OK))
{
MessageBox.Show ("So Far So Good");
}
}
The second form has some fields to fill in and a button "register". I've set the dialogResult of this button to 'ok' in the properties window and also, I think, in the code. When the "register" button in the second form is clicked it checks the input, tries to update a database and closes if successful. Here is that bit of code:
dbConnection db = new dbConnection();
db.dbConnect();
if (db.dbRegisterVehicle(txtNewReg.Text, txtNewMake.Text, txtNewModel.Text, txtNewColour.Text, OwnerID))
{
// if insert worked close
this.DialogResult = DialogResult.OK;
this.Close();
}
db.dbDisconnect();
I'm sure what to try, or what I might be over looking.
Use ShowDialog
newReg = new frmRegisterNew();
var dialogResult = newReg.ShowDialog();
if(dialogResult==DialogResult.OK)
{
....
}
The ShowDialog method is a good way to go but be aware of the differences between Show and ShowDialog. The latter will be modal which means that you can't access your original form until the new form is closed. This is why it blocks the check and may or may not be what you want.
When you call Show, it doesn't block, so that's why your code was immediately checking to see if the DialogResult was equal to OK (it wasn't equal to OK because your new form had barely opened by the time the check was made).
The alternative to using ShowDialog, if you want to use Show, is to handle the new form's closed event.
frmRegisterNew newReg = new frmRegisterNew();
newReg.FormClosed += (s, o) =>
{
if (newReg.DialogResult == DialogResult.OK)
{
MessageBox.Show ("So Far So Good");
}
};
newReg.Show();
This means that your code will continue to work and your new form will not be modal, but when the new form it closed, the FormClosed event handler will be fired. Don't worry if you're not familiar with the event handler notation above (they're called anonymous methods) but you can still use the event handler as normal.
newReg.FormClosed += new FormClosedEventHandler(newReg_FormClosed);
void newReg_FormClosed(object sender, FormClosedEventArgs e)
{
MessageBox.Show ("So Far So Good");
}
Try instantiating the DialogResult class and using it this way:
DialogResult dr = new DialogResult();
newReg = new frmRegisterNew();
dr = frmResgisterNew.ShowDialog();
if ( dr == DialogResult.OK )
//Take an action here.
Form.Show() is non-blocking and will return very quickly. Your check on newReg.DialogResult.Equals(DialogResult.OK)) will therefore occur before the user has had a chance to press the button. Furthermore, note this warning about closing the window:
If a Form is displayed as a modeless window, the value returned by the DialogResult property might not return a value assigned to the form because the form's resources are automatically released when the form is closed.
(via the Form.DialogResult Property msdn library page)
You can either call From.ShowDialog() or, if you need to keep interaction on the main form, pass a delegate for the other form to call when it's completed.
Edit: A couple of points to keep in mind:
In addition to the warning above about closing the form, you have to be careful about trying to access the contents from a method dispatched from newReg's message loop (including the function that called Close()) after it's been disposed.
If you end up using ShowDialog() instead of Show(), however, this.Close() will not dispose the form. In fact, it essentially does nothing since setting DialogResult to anything other than None will automatically hide the form. If you need deterministic clean-up (presumably why you're calling Close() in the first place), you should call newReg.Dispose() after you're done with it in btnRegisterNew_Click. Otherwise, the form will be disposed at some unpredictable time in the future (provided your application doesn't end abnormally in the interim).
If you use an anonymous function as mentioned by keyboardP, be aware that it can get hard to debug when something goes wrong (especially if you're relatively new to the language and framework).
I have an application that has 2 forms. First one is where I do all the job and second one is just for displaying a progressbar.
I want to open the second one from the main form. if I use
Form2 newForm = new Form2();
newForm.Show();
Form2 opens and closes when it needs to open and close, but I cannot see the progress bar. I just can see a blank instead of it.
When I use
Form2 newForm = new Form2();
newForm.ShowDialog();
I can see the progressbar but Form2 doesn't close when it needs. It runs forever, what should I do?
I use a static public variable closeForm to close the second form. When I need to close the form I set
closeForm = true;
and in the second form, I have a timer
private void timer1_Tick(object sender, EventArgs e)
{
if (Form1.closeForm)
{
this.Dispose();
this.Close();
return;
}
else
{
progVal++;
progressBar1.Value = (progVal % 100);
}
}
this is where I put the ProgressBar value and close the form.
When I use show method, I only see blanks instead of the controls in form2. not just the progressbar, and I want form1 to close form2
first of all you need to report progress to progressbar
int iProgressPercentage = (int)(dProgressPercentage * 100);
// update the progress bar
progressBar1.ReportProgress(iProgressPercentage);
try doing that first then call this.close();
As I said above in the comment, you need to check Modal dialog from here Form.ShowDialog Method, and I just quote the following form there:
You can use this method to display a modal dialog box in your application. When this method is called, the code following it is not executed until after the dialog box is closed.
As why you can't see your ProgressBar on Form2 with Show(); you need to provide more information of how you handles it, as if I separate your program into two parts and use two button click to run them (Click button1 to show Form2; and click button2 to close it) I can see your expected result: the progressbar.
Without your further information, my best guess is something running prevents the Form2 to update its GUI.
I want to prevent closing of a form in some cases. I know the usage of OnFormClosing,
but when the form is hidden (Visible==false), the OnFormClosing method is not called.
Is there a way to intercept form closing in this case?
Edit (some more details):
The form is a child in a MdiParent, should stay invisible in the background and wait for calls from another thread (by Invoke).
The MdiParent closes all child windows when the user "disconnects", in this case the above form should stay open, but invisible and still waiting for calls.
When the MidParent itself is closed, all forms should close.
Edit2 (no solution?):
It seems that there is no solution to this. My workaround now is to exclude my not-to-be-closed form in the MdiParent-code, that closes all other forms.
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
// This will cancel the event
e.Cancel = true;
}
Regardless of the reason, this will effectively stop a form from closing.
I have 2 forms ...when i start the application..and use the close "X" from the title bar the entire application closes...now when i select an option from the 1st form in my case it is a button "ADD" as its a phonebook application..it goes to the 2nd form as i have used 1stform.hide() and 2ndform.show()...now when i do "X" from the title bar it doesnt shutdown completely as the 1stform is not closed....how to program it in such a way tht any stage the entire application should close
Your first form is set as the startup form. That means whenever it gets closed, your entire application is closed. And conversely, your application does not close until it gets closed. So when you hide the startup form and show the second form, the user closing the second form does not trigger your application closing because they have only closed a secondary, non-modal dialog.
I recommend changing your design so that the startup form is also the main form of your application. No sense trying to work around built-in functionality that can actually be useful. You want the application to quit when the main form is closed, no matter what other child forms are opened.
But the quick-and-dirty solution in your case is to make a call to Application.Exit. That will close all of the currently open forms and quit your application immediately. As I said just above, I don't so much recommend this approach because having to call Application.Exit from every form's FormClosed event handler is a sign that something has gone seriously wrong in your design.
If the single startup form paradigm doesn't work out for you, you should look into taking matters into your own hands and customizing the Main method in your Program.cs source file. See the answers given to this related question for some ideas on how that might work for you.
What you can do is to use the Form's FormClosing event, and add the following code:
Application.Exit();
This will stop the entire application, and close all windows. However, if a background thread is running, the process itself will survive. In this case you can use:
Environment.Exit();
Add a Application.Exit on every forms's Closing event
like this:
Create an closing event handler first
private void Form_ClosingEventhandler()(object sender, CancelEventArgs e)
{
//Perform any processing if required like saving user settings or cleaning resources
Application.Exit();
}
then bind this event to any form you create.
//Where you create new form and show it.
Form1 frm= new Form1();
//set other properties
frm.Closing += new EventHandler(Form_ClosingEventhandler);
Form2 frm2= new Form2();
//set other properties
frm2.Closing += new EventHandler(Form_ClosingEventhandler);
Surely you don't want to shut down the entire application after the user adds a phone number? You just need to make sure that your main window becomes visible again. Write that like this:
private void AddButton_Click(object sender, EventArgs e) {
var frm = new AddPhoneNumber();
frm.StartPosition = FormStartPosition.Manual;
frm.Location = this.Location;
frm.Size = this.Size; // optional
frm.FormClosing += delegate { this.Show(); };
frm.Show();
this.Hide();
}