Form gets disposed when trying to hide it - c#

I am trying to hide my main form on a certain event and then show it again later. The problem is that the form gets disposed when I hide it.
My code for hiding the form:
private void MessageRecived(object sender)
{
//Do stuff
if (status == NetConnectionStatus.Connected)
{
this.Hide();
}
else if (status == NetConnectionStatus.Disconnected)
{
this.Show();
}
//Do some more stuff
}
When the "this.Show()" method is called, the following exception is thrown:
System.ObjectDisposedException
Additional information: Cannot access a disposed object.
I have also tried to use "this.Visible = false" and "this.SetVisibleCore(false)" but I get the same result.
How can I hide the form without it getting disposed?
EDIT:
I found my mistake: There was an object in my code that referenced the form, and it closed it. Thanks to Justin Harvey who pointed out that something else is using the form.

It seems like your form is Disposed by Garbage Collector or by some other code.
Setup breakpoint in
protected override void Dispose(bool disposing)
method (usualy inside NAME.Designer.cs file)
I've made the following experiment and it works well!
Create new WindwsForms Application
Place Time on main form in Form Designer
Add FormClosingevent handler
Add Time Tick event handler
Write the following code:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
if (MessageBox.Show("Press Yes to Hide only the Form?", "Exit", MessageBoxButtons.YesNo) ==
DialogResult.Yes)
{
e.Cancel = true;
timer1.Enabled = true;
Hide();
}
}
private void timer1_Tick(object sender, EventArgs e)
{
Show();
timer1.Enabled = false;
}

Related

Best Way to Close a Win Form

I need to close a form on a button click event.Here in my example I am hiding the form.Think this is not a good way.When I do only Close() the form is disposed forever and need to rerun the programme to retrieve it.
private void buttonClose_Click(object sender, EventArgs e)
{
this.Close(); //closing frmCalender
}
private void frmCalender_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
this.Hide();
e.Cancel = true;
}
}
Give me the best way to close a C# Windows Form.
If you want to close a form, call .Close().
When I do only Close() the form is disposed forever and need to rerun the programme to retrieve it.
When you close the form, I assume you have no references to it. If so, you can create a new copy of your form via the constructor (var form = new MyForm();).
Otherwise, after closing the form, I believe you should be able to call .Show() on it again, as long as something still has a reference to your form.
I think, the best approach would be:
private void buttonClose_Click(object sender, EventArgs e)
{
this.Hide();
}

Cannot access a disposed object C# (showdialog dispose)

I am new to c# and kind of winging it. using Microsoft Visual C# 2010
I have checked many similar posts and none of the suggestions seem to help
I am getting the following error: "Cannot access a disposed object"
which references the main form here
private void btn_RunPkgs_Click(object sender, EventArgs e)
{
RunPackages rp = new RunPackages();
this.Hide();
rp.ShowDialog();//The error points to this line
this.Show();
}
here is the code that blows up when the security check fails.
private void securityCheck()
{
if (MyGlobals.FormCheck("RUN_JOBS") == 1)
{
InitializeComponent();
}
else
{
//this.BeginInvoke(new MethodInvoker(this.Close));
//this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
MessageBox.Show("You do not have permission to access this form!");
//this.Close();
this.Dispose();
}
}
EDIT
It looks like I am going to go with Adriano Repetti's idea of putting the security where I call the page, but I am a little nervous now having any security on the page.
private void btn_RunPkgs_Click(object sender, EventArgs e)
{
if (MyGlobals.FormCheck("RUN_JOBS") == 1)
{
RunPackages rp = new RunPackages();
this.Hide();
rp.ShowDialog();
this.Show();
}
else
{
MessageBox.Show("Not for You!");
}
}
private void btn_ListUpdater_Click(object sender, EventArgs e)
{
if (MyGlobals.FormCheck("MDM") == 1)
{
ListUpdater lu = new ListUpdater();
this.Hide();
lu.ShowDialog();
this.Show();
}
else
{
MessageBox.Show("Private!");
}
}
EDIT2
Came up with the following possible solution but am nervous to use it because I am new at this and don't know what issues there might be. Any problems with just creating an event handler for form load?
namespace RunPackages
{
public partial class ListUpdater : Form
{
public ListUpdater()
{
InitializeComponent();
this.Load += new EventHandler(securityCheck);
}
private void securityCheck(object sender, EventArgs e)
{
if (MyGlobals.FormCheck("MDM1") == 0)
{
MessageBox.Show("Not Allowed!");
this.Close();
}
}
You can't dispose of the form within the form itself. The ShowDialog() method tries to access the form on exit for things such as DialogResult.
After a form has been disposed almost all of its methods can't be accessed (and most of its properties are invalid).
In your first line of btn_RunPkgs_Click() you create an object and you dispose it inside its constructor. Per se, even if pretty bad habit you may even call Dispose() from within constructor, it may even work but then you try to use such object ShowDialog() will generate ObjectDisposedException. Note that this code will also lead to same result (an exception):
RunPackages rp = new RunPackages();
rp.Dispose();
Yes you may check IsDisposed but that won't make code readable and problem (IMO) is you're mixing things. Constructor shouldn't contain such logic.
The point isn't just where you dispose your form. What's better is to don't even create such form (let me assume, because you call InitializeComponent(), that securityCheck() is called inside form constructor), for this you may use a factory static method:
public static bool TryShowDialog(Form currentForm)
{
if (MyGlobals.FormCheck("RUN_JOBS") != 1)
return false;
if (currentForm != null)
currentForm.Hide();
RunPackages dlg = new RunPackages();
dlg.ShowDialog();
if (currentForm != null)
currentForm.Show();
return true;
}
Your calling function will then be reduced to:
private void btn_RunPkgs_Click(object sender, EventArgs e)
{
RunPackages.TryShowDialog(this);
}
Note that such function is highly eligible for some refactoring (for example to extract code to hide/show existing form). Something like this:
public static bool ShowDialog<T>(Form currentForm, string authorizationId)
where T : Form, new()
{
if (MyGlobals.FormCheck(authorizationId) != 1)
return false;
if (currentForm != null)
currentForm.Hide();
T dlg = new T();
T.ShowDialog();
if (currentForm != null)
currentForm.Show();
return true;
}
Used like this (now code is reused everywhere):
SecurityHelpers.ShowDialog<RunPackages>(this, "RUN_JOBS");
Please note that calling code may be simplified (authorizationId may be an attribute on RunPackages, for example, and also currentForm can be deduced from current active form).
EDIT Calling Close() isn't better, if window handle has not been created (let's simplify little bit: it's created when window is shown) internally it'll call Dispose() (then above applies).
I would not try to disrupt the chaining of events that lead to the form creation.
The side effects are difficult to predict and what works today could not work in future versions.
Instead I would try a different approach
private void securityCheck()
{
if (MyGlobals.FormCheck("RUN_JOBS") == 1)
{
InitializeComponent();
}
else
{
Label message = new Label();
message.Dock = DockStile.Fill;
message.Text("You do not have permission to access this form!.");
message.TextAlign = ContentAlignment.MiddleCenter;
this.Controls.Add(message);
}
}
In this way I let the form show with just one label that covers the entire form surface with your message. The user could only close the form (provided that you have not removed the Control Box)
By the way, this has the advantage of avoiding dangerous oversights because it doesn't require any change on the calling code and the final effect is to effectively block the use of the form.
If you insist in closing the form during its constructor phase then you could get some advices from this question
I came up with the following, can anyone tell me if there are any issues with this?
namespace RunPackages
{
public partial class ListUpdater : Form
{
public ListUpdater()
{
InitializeComponent();
this.Load += new EventHandler(securityCheck);
}
private void securityCheck(object sender, EventArgs e)
{
if (MyGlobals.FormCheck("MDM1") == 0)
{
MessageBox.Show("Not allowed!");
this.Close();
}
}
etc...
Use a flag. For example change the code, like this:
public bool IsDisposed;
private void securityCheck()
{
if (MyGlobals.FormCheck("RUN_JOBS") == 1)
{
InitializeComponent();
}
else
{
//this.BeginInvoke(new MethodInvoker(this.Close));
//this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
MessageBox.Show("You do not have permission to access this form!");
//this.Close();
this.Dispose();
this.IsDisposed = true;
}
}
Then:
private void btn_RunPkgs_Click(object sender, EventArgs e)
{
RunPackages rp = new RunPackages();
if(rp.IsDisposed)
return;
this.Hide();
rp.ShowDialog();//The error points to this line
this.Show();
}

Form.Show(): Cannot access a disposed object

I have been stuck with this for some time now. I can't open a new form on button click.
If i create and .Show() form in the start form constructor i will work. I dont get it! :-(
StartUp Form
public Form1()
{
InitializeComponent();
startmessage();
br = Logic.loadXML("theshiiiiiittt.xml");
br2 = br.Clone();
loadboxes();
//serializeTest();
t = new Thread(contactDBUpdate);
//t.IsBackground = true;
t.Start();
}
Button event:
private void resultButton_Click(object sender, EventArgs e)
{
ResultForm rf = new ResultForm(this);
rf.Show();
this.Enabled = false;
}
Hope this is enough.
In my case it was caused by the fact that i wanted to make my forms non-modal. So i changed them from form.ShowDialog(parentForm) to form.Show().
But that caused the ObjectDisposedException if i try to show a form a second time because somewhere in the code was this.Close();. Form.Close also disposes it.
MSDN:
When a form is closed, all resources created within the object are
closed and the form is disposed.
I just needed to change
this.Close();
to
this.Hide();
Found my code problem.
I took one more look at the Stack trace and found i a message "Icon".
this.Icon.Dispose();
Startupform had this line.
This code fixed my problem:
private void resultButton_Click(object sender, EventArgs e)
{
ResultForm rf = new ResultForm(this);
rf.Icon = this.Icon;
rf.Show();
this.Enabled = false;
}
Thanks for the helping hands...
The problem is that your form object loose the scope and is disposed off.
If you want to keep the dialog open, use Form.ShowDialog();
Try this:
private void resultButton_Click(object sender, EventArgs e)
{
using(ResultForm rf = new ResultForm(this))
{
rf.ShowDialog();
}
this.Enabled = false;
}
Wile Implementing singleton pattern on windows form I got this error too.
The solution is that you have to assign a null value to the static reference in
protected override void Dispose(bool disposing)
by putting simple line.
obj=null; //obj is the static reference in the class.

C# Minimize to Tray

I know you will be thinking "Not again this question", as I found like a hundred results when I searched for it. But when I put in the code as described on the pages here, it just minimizes to right above the start menu.
This is the code I use (I added a message box to see if the code gets triggered, but the message box never pops up):
private void Form1_Resize(object sender, EventArgs e)
{
MessageBox.Show("Works1");
if (WindowState == FormWindowState.Minimized)
{
this.Hide();
}
}
Because I don't know if it links to Form1 or Form, I have tried both, to no avail.
private void Form_Resize(object sender, EventArgs e)
{
MessageBox.Show("Works");
if (WindowState == FormWindowState.Minimized)
{
this.Hide();
}
}
Now, when you double click on the Form, it puts this line in the Form1.Designer.cs:
this.Load += new System.EventHandler(this.Form1_Load);
Do I need a similar line to trigger the minimize event?
As you can see, I am completely lost :)
Oh, and it doesn't minimize to the taskbar, as I am using the following code to hide the form on run:
protected override void OnLoad(EventArgs e)
{
Visible = false; // Hide form window.
ShowInTaskbar = false; // Remove from taskbar.
base.OnLoad(e);
}
You need the event
private void Form1_Resize(object sender, EventArgs e)
{
}
Creating Event Handlers on the Windows Forms Designer
Add a NotifyIcon component to your Form. Make sure you set an icon via the properties pane otherwise it will be invisible.
Create an event handler for the form's Control.SizeChanged event. In that event handler place the following code:
sample code:
private void MainForm_SizeChanged(object sender, EventArgs e)
{
if (WindowState == FormWindowState.Minimized)
ShowInTaskbar = false;
}
And then to make the form visible again the NotifyIcon.MouseDoubleClick event handler you can place the following code:
private void trayIcon_MouseDoubleClick(object sender, MouseEventArgs e)
{
WindowState = FormWindowState.Normal;
ShowInTaskbar = true;
}
The basic thing you need to know is events. Events are triggered when certain things happen to your form (or any control). For example, when the form is resized, or loaded, or clicked, an event is raised. You can hook into this event to execute your own code when the event happens.
In your case you want to execute code to minimize the form, on the event that the form is resized. So you need to hook your method to the resize event. The name of your method is not relevant, so let's use a better name:
private void HideWhenMinimized(object sender, EventArgs e)
{
MessageBox.Show("Works1");
if (WindowState == FormWindowState.Minimized)
{
this.Hide();
}
}
To hook your HideWhenMinimized method into the Resize event of the form, you have to do it like this:
this.Resize += new System.EventHandler(this.HideWhenMinimized);
If you add that line of code in the form's constructor or Load event, then your code gets called as soon as the form is resized.

WPF hide a window in Closing event prevents from application terminating

A simple question again.
I am using a window in a WPF as a child window, where I would rather have the 'X' button hide the window instead of close. For that, I have:
private void Window_Closing(object sender, CancelEventArgs e) {
this.Hide();
e.Cancel = true;
}
The problem is that when the parent window is closed, this never closes and keeps the app alive.
Is there a clean way to deal with this? I thought of adding a Kill flag to all my user controls (windows):
public bool KillMe;
private void Window_Loaded(object sender, RoutedEventArgs e){
KillMe = false;
}
private void Window_Closing(object sender, CancelEventArgs e) {
this.Hide();
if (!KillMe) e.Cancel = true;
}
Then in MainWindow_Closing() I would have to set all window KillMe flags to true.
Any better way than creating additional flags and forgetting to set them before closing?
You could call Shutdown in the "parent's" closing handler... This will cause your Cancel to be ignored.
From Window.Closing:
If Shutdown is called, the Closing event for each window is raised. However, if Closing is canceled, cancellation is ignored.
I usualy have my own AppGeneral static class for such cases. When I'm realy exiting app I'm setting AppGeneral.IsClosing static bool to true. And then, when closing:
private void Window_Closing(object sender, CancelEventArgs e) {
if (!AppGeneral.IsClosing)
{
this.Hide();
e.Cancel = true;
}
}
Also, you can kill the your own process (that's ugly but working :) ) Process.GetCurrentProcess().Kill();
You should use
Application.Current.Shutdown();
inside your master window closing method.
This should override canceling of any subwindow!

Categories

Resources