Is it possible to close a form while the constructor is executing (or simply to stop it showing at this stage)?
I have the following code:
public par
The only thing you could do it set a flag to close it in the constructor, and then closing it in the Shown
event. Of course, if you're doing that, it makes sense to move the code to determine whether it should be closed there in the first place.
Calling Close
from the constructor of the Form is not possible, as it will call Dispose
on a Form that has not yet been created. To close the Form after construction, assign an anonymous event handler to the Load event that closes your Form before it is displayed for the first time:
public partial class MyForm : Form
{
public MyForm()
{
if (ShouldClose())
{
Load += (s, e) => Close();
return;
}
// ...
}
// ...
}
Environment.Exit(...)
is working for me (without window flickering):
public partial class MyForm : Form
{
public MyForm()
{
if (weShouldClose)
{
Environment.Exit(0);
}
}
}
The following works well:
public partial class MyForm : Form
{
public MyForm()
{
if (MyFunc())
{
this.Shown += new EventHandler(MyForm_CloseOnStart);
}
}
private void MyForm_CloseOnStart(object sender, EventArgs e)
{
this.Close();
}
}
I think it is not wise to close a form in the constructor. If you do this, users of your form wouldn't know whether to ShowDialog or not.
The following code would be quite normal use:
// in the parent form:
public void ShowMyForm()
{
MyForm form = new MyForm();
form.propertyA = ...;
from.propertyB = ...;
DialogResult dlgResult = form.ShowDialog(this);
ProcessDialogResult(dlgResult);
}
If you decided in the constructor whether the Form ought to be shown, you would have to add code after construction to decide whether to call ShowDialog or not and whether to Process the dialog result.
Furthermore, are you sure that changing the properties will never influence whether the form is to be shown or not? Also after future changes?
During construction the form is not shown / opened yet. So I'm afraid Close()
doesn't do what you expect.
The neat method is to do the checks that you wanted to do in the constructor in the Form_Load. Add an event handler for form-load and do your checks in the event handler. Use the property DialogResult to indicate that you decided not to show the form.
private void FormMain_Load (object sender, EventArgs e)
{
if (FormShouldNotLoad())
{
this.DialogResult = System.Windows.Forms.DialogResult.Abort;
Close();
// Warning, this does not work, see below, (but we're almost there!)
}
}
The user of the code could check the result of the dialog:
// in the parent form:
public void ShowMyForm()
{
MyForm form = new MyForm();
form.propertyA = ...;
from.propertyB = ...;
DialogResult dlgResult = form.ShowDialog(this);
switch (dlgResult)
{
case System.Windows.Forms.DialogResult.Abort:
ProcessFormNotLoaded();
break;
case System.Windows.Forms.DialogResult.OK:
ProcessFormOk();
break;
// etc.
}
}
However, calling Close() in the event handler for form-load won't work, because Close()
can only be called properly after Load is completed.
Therefore, instead of calling Close()
, you should BeginInvoke
the Close() function, so the Close
function will be called after loading is done:
private void FormMain_Load (object sender, EventArgs e)
{
if (FormShouldNotLoad())
{
this.DialogResult = System.Windows.Forms.DialogResult.Abort;
// invoke the Close function after Load completed
this.BeginInvoke(new MethodInvoker( () => this.CancelLoading())
}
}
If you want your window to never be seen
(no flickering windows that open for an instant and then disappear):
public new void Show()
{
if (MyFunc())
base.Show();
else
; // dispose or whatever
}
Though Show(...)
has 2 overloads and ShowDialog(...)
has 2 too.
Doesn't work for the main form that is opened via Application.Run()
. But who would do that anyways? Except there is also a way to open main form without using Application.Run()
.