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.
Related
I have a form that minimizes when I open a secondary form (using a button click event). I want to be able to restore the original form when closing the secondary form. I have not been able to figure out how to restore the original. Here is the code I have (in example form)
The code from the main form:
private void BtnSecondaryForm_Click(object sender, EventArgs e)
{
// Open the secondary form.
FrmSecondaryForm fsf = new FrmSecondaryForm ();
fsf.Show();
this.WindowState = FormWindowState.Minimized;
}
Code from the secondary form:
private void FrmSecondaryForm_FormClosing(object sender, FormClosingEventArgs e)
{
// I need this code to be able to restore the main form.
}
Please don't just redirect me to someone else's similar question without explaining how I can get this to work in my application. I have looked at the other similar questions here on Stack Overflow already and don't understand how to get this to work.
You should find the form you want or restore, e.g.
using System.Linq;
...
private void FrmSecondaryForm_FormClosing(object sender, FormClosingEventArgs e)
var mainForm = Application
.OpenForms
.OfType<MainForm>()
.LastOrDefault();
if (mainForm != null) {
mainForm.WindowState = FormWindowState.Normal;
}
}
Move FormClosing event handler to primary form. This form is interested in the event anyway. I also changed event from FormClosing to FormClosed. Former can be called many times, but latter is called only once, when the form is actually closed.
private FrmSecondaryForm Fsf = null;
private void BtnSecondaryForm_Click(object sender, EventArgs e)
{
// Open the secondary form.
Fsf = new FrmSecondaryForm();
Fsf.Show();
Fsf.FormClosed += PrimaryForm_SecondaryFormClosed;
this.WindowState = FormWindowState.Minimized;
}
private void PrimaryForm_SecondaryFormClosed(object sender, FormClosedEventArgs e)
{
Fsf.FormClosed -= PrimaryForm_SecondaryFormClosed;
Fsf.Dispose();
Fsf = null;
this.WindowState = FormWindowState.Normal;
}
So you need Form2 to interact with Form1, which means that Form2 needs a reference to it.
Best is to do this during construction. But with forms, you should always keep a default no-parameter constructor, so we need to add a new one and make the original private.
//Add a new property (or field if you wish)
private Form formToMinimise { get; }
//Change this to be private
private SecondaryForm()
{
InitializeComponent();
}
//Add this new constructor as public
public SecondaryForm(Form form): this()
{
formToMinimise = form;
}
Now closing and restore original. We do a null check, just in case
private void FrmSecondaryForm_FormClosing(object sender, FormClosingEventArgs e)
{
formToMinimise?.WindowState = FormWindowState.Normal ;
}
Now you amend the creation and calling of your second form like this
private void BtnSecondaryForm_Click(object sender, EventArgs e)
{
// Create the secondary form with reference to this form
FrmSecondaryForm fsf = new FrmSecondaryForm(this);
fsf.Show();
this.WindowState = FormWindowState.Minimized;
}
While wanting to use using statement, I came across a scenario that I don't understand :
private void RoomMealHistory_Click(object sender, EventArgs e)
{
MealRoomPlanning fMealRoomPlanning = new MealRoomPlanning(true);
fMealRoomPlanning .MdiParent = this;
fMealRoomPlanning.Show();
}
This code works correctly and my window is a MdiChild.
However, the following code does not work :
private void RoomMealHistory_Click(object sender, EventArgs e)
{
using (MealRoomPlanning fMealRoomPlanning = new MealRoomPlanning(true))
{
MdiParent = this;
fMealRoomPlanning.Show();
}
}
ArgumentException: 'A form cannot be an MDI child and an MDI parent at the same time.
I also tried to replace this with this.ParentForm doesn't work anymore.
Is there a problem with the scope of this?
In your first snippet, you set the MdiParent-Property of fMealRoomPlanning.
In your second snippet, you set MdiParent of your own class instance (this.MdiParent).
You should set it on the object you are using:
private void RoomMealHistory_Click(object sender, EventArgs e)
{
using (MealRoomPlanning fMealRoomPlanning = new MealRoomPlanning(true))
{
fMealRoomPlanning.MdiParent = this;
fMealRoomPlanning.Show();
}
}
That's why many style-checks recommend using the this-Qualifier although it is redundant. This makes it more clear if you set a local, global or class variable.
Finally I have just understood that Using is not necessary for non-modal Form.
When a non modal form is closed, the Dispose will automatically be called by WinForms.
Unlike Forms opened with ShowDialog for which the Dispose is not called automatically.
Try changing MdiParent = this to fMealRoomPlanning.MdiParent = this
Try Changing the 2nd Code, After creating object for MealRoomPlanning class
change MdiParent = this; to fMealRoomPlanning.MdiParent = this;
private void RoomMealHistory_Click(object sender, EventArgs e)
{
using (MealRoomPlanning fMealRoomPlanning = new MealRoomPlanning(true))
{
fMealRoomPlanning.MdiParent = this;
fMealRoomPlanning.Show();
}
}
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;
}
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();
}
I have a small problem, when I open a new window in WPF like so:
private void button2_Click(object sender, RoutedEventArgs e)
{
var newWindow = new Main();
newWindow.Show();
}
If I try to use Application.Current.Shutdown(); at the end of it my entire application shuts down rather than just my first initial window. So my question would be is there a way to open a new window while closing the previous window safely?
Thanks :)
I'd do something like this:
//Somewhere in your class
YourOtherForm otherForm = null;
//then, on the event handler
private void button2_Click(object sender, RoutedEventArgs e) {
if((otherForm.IsDisposed) || (null == otherForm)) {
otherForm = new YourOtherForm();
// or, this is an MDI or something
// otherForm = new YourOtherForm(this);
// assuming you have an extra constructor to pass the parent
}
otherForm.Show();
this.Close(); // or this.Hide(); if it's the main form
}
Edit: I haven't tested this code tho..
The only way to do this is to run the program externally (I will find the code to do this shortly). Otherwise, anything that is created from within the main application will be destroyed when the parent shuts down.
The code to spin up a new program:
System.Diagnostics.Process.Start("program.exe");
You will need to change the ShutdownMode to OnLastWindowClose in your App.xaml.