I am getting the error message Cannot access a disposed object.
Object name: 'ApplicationProperties'. when I tryo to re-open a form after closing it. I have noticed this is from exiting forms, and exiting is "Disposing" of them, so I have put the following code in all of my accept buttons, and cancel buttons (any button that closes a form).
this.Hide();
this.Parent = null;
This code is just hiding the form. Not closing the form.
So what my problem is, is that when I click the 'x' button on the form, then try to re-open the form I still get the error message. I have tried a couple differnet ways to modify the exiting funciton of the form such as:
private void ApplicationProperties_FormClosing(object sender, FormClosingEventArgs e)
{
//Hiding the window, because closing it makes the window unaccessible.
this.Hide();
this.Parent = null;
}
But this has brought me no luck. I was wondering if anyone knows how to solve this problem. Here is the code that is working for me inside my cancel and accept buttons. It is the same for all of my buttons that close forms.
private void OptionsCancelbtn_Click(object sender, EventArgs e)
{
//Hiding the window, because closing it makes the window unaccessible.
this.Hide();
this.Parent = null;
}
I have declared the instance at the top of my class on form1, and have a button inside form1 that opens form2.
public partial class MainBox : Form
{
//Making a name for the ApplicationProperties form. It can be opened when called.
ApplicationProperties ApplicationPropertiesWindow = new ApplicationProperties();
private void ApplicationPropertiesbtn_Click(object sender, EventArgs e)
{
//Show the properties window.
ApplicationPropertiesWindow.Show();
}//End ApplicationProperties button.
}
After I close the program with the 'x' button on the second form I cannot access form2 again because of the error message firing at ApplicationPropertiesWindow.Show();
Inside form2 I have the following code:
public partial class ApplicationProperties : Form
{
//Creates and sets the instance MainBoxWindow.
public MainBox MainBoxWindow { get; set; }
Try this in your FormClosing event:
private void ApplicationProperties_FormClosing(object sender, FormClosingEventArgs e)
{
//Hiding the window, because closing it makes the window unaccessible.
this.Hide();
this.Parent = null;
e.Cancel = true; //hides the form, cancels closing event
}
cause right now it is still closing the form, thus still causing the error.
After I close the program with the 'x' button on the second form I
cannot access form2 again because of the error message firing at
ApplicationPropertiesWindow.Show();
When a form is closed (Form.Close), the form itself and all of its associated resources are freed. There are only two exceptions to this automatic disposal, as noted in the documentation:
The form is part of a MDI application and not visible.
The form was displayed as a modal dialog using ShowDialog (as opposed to Show). It is designed this way so that you can access properties of the dialog (e.g. to retrieve user input) after the user has closed it.
In both of these special cases, you are responsible for manually calling the Dispose method of the form. The second case is by far the most common (no one really uses the MDI paradigm anymore), and is handled easily with a using statement:
using (MyDialogBox dlg = new MyDialogBox())
{
DialogResult result = dlg.ShowModal(this);
if (result == DialogResult.Yes)
{
// access members of "dlg", and
// do whatever the user asked
}
} // the Dispose method is automatically called here
In your case, as is typical, the call to the Close method is closing and destroying the form. You already know that you cannot access a disposed object (because it no longer exists!), so that's why you're getting the exception when you try to show it. In order to show the form again after it has been closed, you need to create a new instance of the form class:
MyForm frm = new MyForm();
frm.Show();
// ...
frm.Close();
This is really the best method. A new instance of the form will be identical to the one you're closing because it was created from the same class. You would do best to start thinking in object-oriented terms and avoid singleton-based designs whenever possible. Each form that shows up on the screen is a new, independent object. Once that object is closed and destroyed, you cannot use it any longer. If you want to use it again, you need to create a new object and display it.
The Hide method is more of a hack, useful only when you want to temporarily hide the current instance of a form while still retaining its state (e.g., the values of its member properties, its control states, etc.). This works only with singleton objects that will never be destroyed, and must be carefully designed and maintained. It also means that this form object consumes resources all the time, whether it is being used or not, which is wasteful.
If you must do this, you'll need to track down what is causing your form instance to be disposed. Without seeing all of your code, it's hard for me to do anything but guess at where the problem might be. It is likely related to your use of the AcceptButton and/or CancelButton properties. Either way, the best and cleanest solution is to override the OnFormClosing method and prevent your form from ever being closed. You'll hide it instead:
public class MyForm : Form
{
protected virtual void OnFormClosing(FormClosingEventArgs e)
{
// Prevent the form from closing.
e.Cancel = true;
// Hide it instead.
this.Hide();
}
// ...other code in your form class
}
The advantage of this is that you only have to have the code in one place, local to the responsible class, rather than exposed to external code and scattered throughout your application. And of course, it also prevents the form from ever being closed by framework code outside of your control.
I have no idea why you're setting the Parent property to null. A top-level window (which is what all forms are) can never have a parent. Only child windows (e.g. controls) have parents. It can have an owner, but it will not necessarily. It depends on whether you pass an owner window as an argument when calling the Show method.
First remove this.Parent=null bcose this is not required when you hiding the Form
Now when you hiding the Form and if you still want to access this Form store form in static var . Bcous when object is no longer in use garbage collector dispose it and it will no longer available .
The problem, at least perhaps part of it, looks like a bit of class interdependence.
When you initialize an ApplicationProperties instance, you're creating a reference to a MainBox object, but in the definition of the MainBox class, you're creating a new ApplicationsProperties object, which references a MainBox.... I'm even confusing myself. Is MainBox your parent form, the one that loads when you start the application?
I wouldn't be surprised if some stuff in MainBox is getting destroyed inadvertently if you set a reference to it in the ApplicationProperites class... which is disposing when you click "X". Again, this is an educated guess; I'm not sure if that's the reason but even if the code isn't wrong per se, it looks quirky to me.
If you want your ApplicationProperties window to last forever and to simplify things, just initialize a static instance of it at the beginning of whatever form is going to persist the duration of your application, and show/hide it similar to what you were attempting originally. If you want to be efficient and fundamental, construct and dispose ApplicationProperties whenever you need to let the user modify it, but kill the circular dependency.
Related
I'm trying to show a Form before an application's start and get its DialogResult, so I'm just creating it and using ShowDialog (because Application.Run's return value is void).
What I'm worried about is that it might get 'hijacked' by mistake by some other Form that might be shown at the time. Not by this application, obviously. See What is the meaning of Form.Show(null)? that it's not advisable to use the parameterless overload of ShowDialog.
I have tested and seen that the Form's Owner property was null. But will it always be so? Or should I create a Form and use that as the Owner without showing it? That seems a strange solution but logically it should avoid any problem. Or will that introduce new ones?
Not by this application, obviously
This is already taken care of by Windows, it enforces a strong separation between processes and windows owned by threads. A typical choice for the owner of a dialog for example is the window returned by GetActiveWindow(). The active window is a property of a thread. Which explains for example why a MessageBox.Show() call made from a worker thread is never modal to the rest of the windows.
Making a window modal against the windows of another process is technically possible but requires lots of effort. The app would have to call AttachThreadInput(), a very unsubtle winapi function that nobody ever calls by accident. Also a great source of deadlock.
Unless you are programming in a boat near the Somali coast, there is no good reason to fear your window getting hijacked.
[STAThread]
static void Main()
{
Form1 form1 = new Form1();
//here I suppose the form you want to show
Form1 form2 = new Form2();
form2.ShowDialog(form1);
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(form1);
}
Basically you use ShowDialog() when there are no parents for this window. Usually this happens for the main window. If you are opening one window after another, while closing previous, then there will be multiple ShowDialog()s.
If you are showing dialog (which is also a window), then you can specify it's parent to achieve a certain behavior. To example, when alt-tabbing to that window, it's dialog will be shown in front. Think about this as making child-parent relations.
I don't know about the case, when multiple forms are the claiming same parent. But it sounds like a clear mistake, to example:
public Form1 FormMain = new Form1();
...
// show main form
FormMain.ShowDialog();
...
// somewhere in the main form - show dialog
Form2 form2 = new Form2();
form2.ShowDialog(FormMain);
...
// somewhere in form2 - show dialog
Form3 form3 = new Form3();
form3.ShowDialog(FormMain); // wrong, should be form2!
This is not tested because I couldn't recreate a case where the parent is ever anything but null (i.e. a reference to a third-party un-managed parent), but maybe you could do something like this on your form to set the parent to null if it changes:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
this.ParentChanged += MyParentChanged;
}
public void MyParentChanged(Object sender, EventArgs e)
{
this.Parent = null;
}
}
I want to access variables of a form from another form. On clicking a button inside my Main form, I want to set my Main form as Parent, then bring up another form (child form) wherein I will access variables of the Main form. My click handler is as follow:
private void btnSystem_Click(object sender, EventArgs e)
{
Form_EnterPassword EP = new Form_EnterPassword();
EP.Parent = this; //error: Top-level control cannot be added to a control
EP.ShowDialog();
}
It compiles fine without any error. However, when I run the Main form and click on the System button, it throws me an exception. I do something similar in another code (not mine) with the same button click, and encounter no error (just with setting Main form as Parent).
What am I doing wrong? Is there something in my Main code that cause this?
Best way would be to use EP.ShowDialog(this) and later use Owner property.
You need the EP.TopLevel property to be set to false. It will let you to set a parent to it.
Further reading.
In case you only want to access variables and controls of another form, then maybe you can reach it in other ways, not trough a Parent relationship.
OK,
apparently the way to do it is to call
Form_Child.ShowDialog(this)
and then I can call
FromParent_aVariable = ((Form_Parent)this.Owner).aVariable;
or if I define aVariable in the namespace Properties then
FromParent_aVariable = NameSpace.Properties.Settings.Default.aVariable;
there are two ways.
Form_EnterPassword EP = new Form_EnterPassword();
EP.MdiParent = this;
EP.Show();
try this way, it helps for me. you need to set principalform as isMdicontainer = true at the form properties
I had a similar situation recently.
I was attempting something similar but by controlling the Child Forms from a different class.
Note(s):
You're trying to set the Child Form(s) "TopMost" to something that does not allow it.
In this case the "MdiContainer".
To accomplish this:
• Disable MainForm "isMdiContainer" property (its use is kind of obsolete anyway).
• Set the Form(s) TopMost properties to true.
• You should now be able to accomplish your feature.
**Code Example:**
/* On your Main Form Class */
private void btnSystem_Click(object sender, EventArgs e)
{
// Instantiate the Form_EnterPassword by passing the MainForm
Form_EnterPassword EP = new Form_EnterPassword(this);
EP.Show(); // No longer as modal Form to display in front.
}
/* Under your EnterPassword Form Class */
// Do not create a new Instance of MyMainForm.
// You want to use the same thread as your MainForm
private MyMainForm mainForm;
/* Constructor */
public Form_EnterPassword(MyMainForm form)
{
mainForm = form;
this.Owner = mainForm; // "this" refers to the: EnterPassword Form.
}
Remarks:
The only additional thing that you (may) have to do, (to achieve perfection) is to check the MainForm > WindowState; and create a code block to minimize or bring the Forms to their specific state.
i.e:
if (WindowState == FormWindowState.Minimized)
{ /* Code to Minimize all the Child Forms. */ }
else { /* Code to bring all Forms to their "Normal" State */ }
Writing this way, made the dialog display on the center of the parent form.
Form_Child.StartPosition = FormStartPosition.CenterParent;
Form_Child.ShowDialog(this);
When Form2 is closed, via it's X button, the Main form is sometimes hidden as well, but not always. Often times the Main form is hidden after initial 'newForm' button click and other times many open-close operations are required before the Main form gets hidden on Form2's closing. Why is this happening? Why is it irregular?
This is a small test code for a larger application I'm working on. In that application a thread continuously reads the network stream and when a particular message is encountered a modal form is displayed. The user can close that modal form or it can be told to close itself by a different network message. In this event, to give the user some time to view the data that the form is displaying I implemented a delayed form closing for that form. When the form is running its delay closing code, another message can come in over the network that will open up a new instance of this form in which case, I observed, that once the timer of the original form runs out, the original form is left displayed until the new instance is closed. Calling Hide in the FormClosing event handler closes the original form if more than one instances of it are running, but it has this side effect of hiding the entire application (the Main form) when the last instance of this form is closed, either by the user or by the delayed closing code. And again, the entire application is not always hidden, but it does happen.
//Main form's 'newForm' button
private void btn_newForm_Click(object sender, EventArgs e)
{
Form2 f = new Form2();
f.ShowDialog();
}
public partial class Form2 : Form
{
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
Hide();
}
}
Update (from the application I'm working on):
The problem is shown visually below. The top part of the picture, labeled "A", represents the situation where the first modal dialog (greyed out) was instantiated and it is in the process of being auto closed after 4 seconds have elapsed. The second instance (blue window heading) is active and awaiting input. In the lower part of the picture, labeled "B", the counter to closing of the first instance has completed, yet the first instance remains visible. Adding Hide does not change picture "A" but picture "B" would only be showing the active modal dialog, which is what I want. If Hide is not used and we have the case shown in "B", once the active modal dialog is closed the inactive dialog will disappear together with the active one, but no sooner. At this time my main form will be hidden as well, sometimes.
Your main form doesn't get hidden, it disappears behind another window. The flaw in your code is that for a brief moment none of your windows can get the focus. Your main window can't get the focus, it got disabled by your dialog and won't get re-enabled until the dialog is fully closed. Your dialog can't get the focus, you hide it. So Windows goes looking for another window to give the focus to and can only pick a window owned by another application. Like Visual Studio, nice and big so your main window is well covered by it.
Not sure what you are trying to do, it doesn't make sense to call Hide() since the dialog will close a couple of microseconds later. Just delete the statement.
I am not sure if I am right but maybe you forgot to add e.Cancel = true; to your closing event.
Second, I think using a modal form is only usefull when you expect an action like OK or CANCEL from user, that is where DialogResults comes handy. It sounds strange if this happens time to time not all the time! maybe you can try like this:
//Main form's 'newForm' button
//Define form in your mainform
private Form2 f;
private void btn_newForm_Click(object sender, EventArgs e)
{
if(f != null) { f.Show(); return; }
f = new Form2()
f.FormClosing += delegate { f.Hide(); };
f.Show();
}
I know the topic is quite old, but I recently had to look for answers for this precise question.
Why hiding the (child modal) form instead of closing it ?
I may be wrong, but I think that in some cases, hidding the modal child form instead of closing it is sometimes useful.
For example, I'm using a class that is a custom tree of grids. Think of something like an Excel Document with multiples tables (sheets) and each table can have child tables. A very powerful manner to store datas that can be used by multiple objects and multiple forms at a time.
Now, this "TreeTable_Class" object has an inbuilt custom form that actually shows the content of one of its tables at a time in a GridView, and you can select which table to show by selecting it in a Treeview. You can see here that the "Database Editor" is actually and MDI Form that can load the Form from any TreeTable_Class.
And this is the Form I use to edit the content of a Cell for a given (selected) Table (I've chosen another cell with long text content from another table in this database)
Now, when you choose to close the custom form instead of hiding it, that form will be unaccessible, you can't show it anymore, and you get an exception (no instance of the object) Somewhat, it isn't disposed yet (so the check If MyForm Is Nothing Then... is useless) I know I have to implement the GarbageCollector and dispose the Child Form manually, but it's outside the scope of this topic.
Anyway, my class could use a large amount of memory, of datas, and if I had to rebuilt ALL the contents each time I want to show a new instance of that form, that would be a large amount of workload in my application. That's why I have chosen to hide the form instead of closing it until the main application exits or when a specific CloseFormAndDispose() method is explicitly called, either by the program, or if I make this option available for the user via an user interface.
Workaround try :
This is the workaround I've found to override the "form replaced by another because none of the parent/child ones could be retrieved" :
Sorry, I'm in VB.. but you can use a tool to convert this to C#, or do it manually, it's pretty simple..
// This is the child, a Cell Editor that can edit the content of a Cell.
Protected WithEvents _CellEditor As CellEditor_Form = Nothing
This Editor form is a member of TreeTable_Form, a form that can actually show and edit the content of the whole Database File (a single file)
And this TreeTable_Form class contains a routine that handles CellEditor closing event
Public Partial Class TreeTable_Form
// Sorry. The "WithEvents" in C# is a litte bit complex to me... So, in VB :
Protected WithEvents _CellEditor As CellEditor_Form = Nothing
// ...
// CellEditor handling method (I used a Code converter...) :
// The original VB declaration is :
// Protected Sub RecallFormAfterCellEditorHidden() Handles _CellEditor.Closed
// You'll have to write specific Event handler for _CellEditor object declared above...
protected void RecallFocusAfterCellEditorHidden()
{
Application.DoEvents();
this.Focus();
}
End Class
This tiny protected void RecallFormAfterCellEditorHidden() method in your Class (if you are using a class that contains Forms) or in your Main From, assuming that your main form contains the child forms (dialogs) will try to force the focus on your Application or MainForm...
By the way, TreeTable_Form is actually a component of TreeTable_Class. The later is an object that can be used anywhere you want. In a Main Form Application, in another Class, in a dialog, anywhere... and could be passed by reference to share its contents between several items. And this TreeTable_Class contains a RecallFocusAfterTreeViewerHidden() method that handles the closing of that form. That means, the Form or Application that actually uses the class will get the focus each time you close the its child Form. I've made it that way to get an object that could be used anywhere
We still get problems !
However, this method will make your application flicker a bit each time you close your child dialog, and doesn't succeed at 100% ! Sometimes, my parent form still disappear from screen and gets struck behind another window. Alt+TAB wont helt either. But this happens less than without this method trick. I don't have any better answer at this time, still searching... I'll come back here if I find out how. I'm using this custom made application in my work to write memos during meetings for example, and produce PV (procès verbal - french sorry) in PDF or DOCx on the fly...
And I'm sorry, I'm in VB, not C#. Hope this helps a little, until we find a better workaround for this...
Does anyone know how can I know if the Windows Form Application (C#) is open or that the client closed it?
(In my App I have a Windows Form Application (Form1) that allow the user to open another Forms (Form2). I want to know if the Form2 is open or close.)
I need to know that because I run the Form2 from a thread, and I want to make the thread runnig until the user close Form2.
Many thanks!
You can check if a form of a given type is open in your application like this (using LINQ):
if (Application.OpenForms.OfType<Form2>().Count() > 0)
{
// there is an instance of Form2 loaded
}
You need to elaborate on your question a bit more. Are you talking about monitoring the application from another application? Or that one form needs to know if another one is open? Or a form needs to know when another form closes?
There are a couple of ways to monitor forms closing within the same application.
Calling ShowDialog() on your form instead of Show() will ensure that code following the ShowDialog() call doesn't get executed until the user closes the form.
The Form class has a Visible property, which returns true/false depending on whether the form is visible or not.
As for the application itself, there is an ApplicationExit event on the static Application class which gets called just before the application closes so you could listen to that event if, for example, you need to perform some clean-up on exit.
If you want to run only single instance of application, check this link.
There you will also see how to check whether a process is still active.
If you mean MDI application with its child forms:
private Dictionary<Type, Form> SingleInstanceForms = new Dictionary<Type, Form>();
public Form ActivateForm<T>() where T : Form, new()
{
Cursor.Current = Cursors.WaitCursor;
if (!this.SingleInstanceForms.ContainsKey(typeof(T)))
{
T newForm = new T();
//setup child
newForm.MdiParent = this;
newForm.WindowState = FormWindowState.Maximized;
//newForm.Icon = Icon;
newForm.FormClosed += new FormClosedEventHandler(delegate(object sender, FormClosedEventArgs e)
{
this.SingleInstanceForms.Remove(sender.GetType());
});
this.SingleInstanceForms.Add(typeof(T), newForm);
newForm.Show();
this.Refresh();
}
Form formToActivate = this.SingleInstanceForms[typeof(T)];
formToActivate.Activate();
Cursor.Current = Cursors.Default;
return formToActivate;
}
this will create the form child if hasn't been created yet and activate it if it has been created.
sample: ActivateForm<dlgChildOne>();
I have a very strange behavior that only seems to happen on one form.
Basically I am creating an instance of a Form, and calling Show() to display the form non-blocking. In that form's Load event handler, I have some logic that may call this.Close() under certain circumstances. This closes the form, but then the form Show() method in the client code throws an ObjectDisposedException.
The stack trace from the ObjectDisposedException is as follows:
at System.Windows.Forms.Control.CreateHandle()
at System.Windows.Forms.Form.CreateHandle()
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.ContainerControl.FocusActiveControlInternal()
at System.Windows.Forms.Form.SetVisibleCore(Boolean value)
at System.Windows.Forms.Control.Show()
...etc.
This is what I'm seeing happen:
Control.Show() is called
my form is launched
the OnFormLoad method is called
the FormLoad event handler is called, inside of which I call this.Close()
the OnFormClosing method is called
the FormClosing event handler is called
Dispose is called on my form and all it's user controls
and then somewhere toward the end of the Control.Show() method, it tries to get a handle to the form, which freaks out and throws an exception because the object is marked disposed.
My real question is, why can I do this exact same thing on every other form I have without exceptions? Is it a GC issue? I've tried putting a GC.Collect() call right after the this.Close() and it makes no difference. Like I said, it happens 100% of the time on this form, and never anywhere else, regardless of child user controls, scope of the form variable, etc.
Any ideas?
The best way to do so :
this.BeginInvoke(new MethodInvoker(this.Close));
this is the most simple way you wont get ObjectDisposedException
I know this is an old issue but no one seemed to have posted the obvoius answer.
You say you call Control.Show() and then Form.Close() and then the form is Disposed of. Well, unless you use MDI or use ShowDialog that's just as documented. Though, the short version of the Close() documentation is "Closes the form", it actually also disposes it implicitly under certain conditions.
See the remarks section:
http://msdn.microsoft.com/en-us/library/system.windows.forms.form.close.aspx
If you want to show a form again. Use the Hide() method instead of Close().
Hope that helps other searching souls.
And guys, don't stop searching at "I don't know why it works sometimes". That becomes buggy software with lots of defensive "I'll call this method again just in case" stuff. Not good.
Ok, hate to answer my own question, but this was driving me nuts, and it was one of the hardest bugs to reproduce I've ever seen.
On my form I'm overriding the OnFormLoad and OnFormClose methods, where I save/restore the form's Size, Location, and WindowState to/from the registry. I took this code out and it fixed the problem. The weird thing is, I put it back and the problem didn't come back.
I finally reproduced the problem: you have to let the form open fully, maximize it, and then close it so that the Maximized state is saved to the registry. Then when you open it again, it will set it to Maximized, and if it closes in the Load handler, it tries to access the Size/Location as it's closing. Apparently accessing these values in the OnFormClosing method causes the form to try to focus IF AND ONLY IF the form is maximized, which is illegal, since the form has been disposed.
So basically, you can't access Form display properties in the OnFormClosing method of a form, if that form is going to call Close from it's Load event.(Unless you check the Disposed prop first)
pretty specific piece of Winforms wisdom I know, but I'm writing it down anyway.
If you want to close a form as if the user pressed the cross in the upper right corner (usually means cancel), just add the following code.
this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.Close();
This also works in the form load function:
private void MyForm_Load (object sender, EventArgs e)
{
// do some initializations
if (!ContinueLoadingForm())
{
this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.Close();
return;
}
// continue loading the form
}
If you don't want the form to be visible for a short while, set the Visible property false (for example in the designer or constructor), and set it back to true when you are certain the program can continue loading.
In load event is not realy good idea close the form. Do it after the Activated event.
protected override void CreateHandle()
{
base.CreateHandle();
if (FormMustClose) //FormMustClose is a variable in the loadevent.
{
Close();
}
}
One possibility:
They may have a timer on this form, that is being initialized and enabled in their FormLoad event. The timer would need to be disabled and stopped as well, before the form was closed, if the timer is trying to access the form when it's fired.
I've seen forms before that do this...
It seems to me, without looking closely at it, that the cleanest way to accomplish what you want might be to make a custom form class deriving from Form, and override OnFormLoad(...) and/or Show() to check for your condition and cancel out early.
That said, I don't know why it would work sometimes and not other times.
Have you tried stepping into the .net code to see what line of code is being called when the exception is occuring? If you have VS 2008 you can do so by going to Tools --> Options --> Debugging and select the Enable .NET Framework Source Stepping. Be warned, this may take a while to download all of the necessary files, but this way you can step into the form.Show() and see exactly what is going on.
Ok, it turns out it's a little simpler and more generic than I thought, but still weird and obscure.
If you're saving/loading the form Size/Location/WindowState when the form loads/closes like we do, you have to make sure that the OnLoad method calls base.OnLoad first so that the Form Load event handler fires, and THEN set the properties. Not doing so will only cause a problem if the form calls Close from inside the Load method. You'll get an ObjectDisposedException on the Show call after the form closing event is done.
My head hurts.
Form.Shown() Is the trick too.
As I understand it, setting the DialogResult of the form will close the form - may have to be other than DialogResult.None. (i.e. you don't need to then call the Form.Close() method).
The issue is also in part that if elsewhere in code, you are accessing a property of the form or control within it, that may prevent the form from closing.
It may also be best if as has been suggested, you have a property e.g.
private bool _loadedOk = false;
in your form which you set in your initialisation code. In one of the later events after Form_Loaded, you then interrogate this and close the form if it's false.
Perhaps someone can suggest the best event to do this in??
If you want to close the form without flicker, the best way I found was override SetVisibleCore Method:
public partial class MyForm : Form
{
...
protected override void SetVisibleCore(bool value)
{
if (value && !IsHandleCreated && !ContinueLoadingForm())
{
base.SetVisibleCore(false);
this.Close();
return;
}
base.SetVisibleCore(value);
}
}
Then you can simply do:
...
var myForm = new MyForm();
myForm.Show();
...
The Form only will appear if ContinueLoadingForm() be true, this works with ShowDialog() and Application.Run() as well.
Expanding on RCMAN's answer in this thread (which got me 99% of the way to the finish line) ...
Here is the code I ended up using which also avoids the screen flicker:
Me.FormBorderStyle = FormBorderStyle.None
Me.Opacity = 0.01
Me.MinimumSize = New Size(1, 1)
Me.Size = Me.MinimumSize
Me.Location = New Point(1, 1)
BeginInvoke(New MethodInvoker(AddressOf Me.Close))
Additionally, to avoid the message "This program might not have run correctly" I applied a manifest change as described by mik here:
How to prevent "This program might not have installed correctly" messages on Vista