Re-open child form - c#

I have one Main form and two types of child form
MainForm
ChildFormA - unique
ChildFormB - have multiple forms of this type
I create ChildFormA with:
ChildFormA form1 = new ChildFormA();
form1.MdiParent = this;
form1.Show();
But when i close it with:
form1.Close();
I can't re-open it.
I've already read some tips that I can Hide this form instead or closing it. But the X button still closes the form.
How to re-open or how to prevent the X button to close and simple hide it?

If you want your child form to remain in its state, you have to subscribe to the FormClosing event and set the Cancel property of the event argument to true.
public ChildForm()
{
...
FormClosing += new FormClosingEventHandler(ChildForm_FormClosing);
}
void ChildForm_FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
Hide();
}
Keep in mind, that you're form will not get disposed, if you don't add more logic to this.
Otherwise, you can just create a new instance of it.

Create a new instance of ChildFormA.

You should create a Child Form only Once .
ChildFormA form1 = new ChildFormA();
if(form1 == null)
{
form1.MdiParent = this;
form1.Show();
}
else
form1.Show();
than you should use Matthias Koch solution ,on child Forms
void FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
Hide();
}
Also Keep ChilFormA as a MDI Class Field ,so you won't lose Ref. to it.

to prevent the form from closing is described here. I would also advice hide, but maybe it works to set visible to false...

You could use the Singleton pattern in for this Form.
http://csharpindepth.com/Articles/General/Singleton.aspx
Look at the 4th approach
Then you would access it using the static instance instead of creating a new one.
You still need Matthias Koch solution ,on child Forms
void FormClosing(object sender, FormClosingEventArgs e)
{
e.Cancel = true;
Hide();
}
If you need further help with the Singleton pattern, please say so.

Related

Closing multiple windows form with single click

I want to close two forms at the same time. I have one main form that starts with program. when user click button, the main form will hide and other form will pop up. on the second form if user click "back to main " button, it should hide second form and show main form. But the problem is if user tries to close the second form it should close the main form as well. How can i close the main form as well
I would just use the Application.Exit() for what is requested by this thread.
Application.Exit();
UPDATE: corrected
I had said this will not call the form closing events but in documentation it does actually call it here is a link to the documentation
http://msdn.microsoft.com/en-us/library/ms157894(v=vs.110).aspx
It was better if you specified what codes you wrote for going back to main form, so I could help you by changing your codes. But now because I don't know how you did it, I have to write codes for both of those tasks.
It can be possible using a Boolean variable to do what you want. Follow bellow codes:
public partial class MainForm : Form
{
//"Click" event of the button that should opens the second form:
private void goToSecondForm_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2(); //Or you can write it out of this method.
this.Hide(); //Hides the main form.
f2.ShowDialog(); // Shows the second form.
this.Show(); // Shows the main form again, after closing the second form using your own button.
}
}
public partial class Form2 : Form
{
bool selfClose = false; //False shows that user closed the second form by default button and true shows that user closed it by your own button.
//"Click" event of the button that should closes just the second form and returns user to the main form:
private void ownCloseButton_Click(object sender, EventArgs e)
{
selfClose = true; //Means user clicked on your own button.
this.Close(); //So the program closes the second form and runs f2_FormClosed method, but because selfClose became true here, happened nothing there and program will go back to goToSecondForm_Click method in the main form and will run this.Show() .
}
//"FormClosed" event of the second form :
//Whether user clicked on your own button or on the default one, this method will run.
private void f2_FormClosed(object sender, FormClosedEventArgs e)
{
if (!selfClose) //It means user didn't click on your own button and both of forms must be closed .
Application.Exit(); //So the program closes all of forms (actually closes the program) and couldn't access to any other commands (including this.Show() in goToSecondForm_Click method).
}
}
As others have said, you need to somehow call .Close() on the main form when your child form is closed. However, as you've pointed out, you don't have a reference to the main form automatically in your child form! That leaves you with a few options.
1. Exit the application immediately.
This is done by calling Application.Exit(); in your child form's "back to main" button's click event handler. It will immediately close all forms, which might simply be what you want.
// .. ChildForm code ..
void OnBackToMainClicked(object sender, EventArgs e)
{
Application.Exit();
}
2. Pass a reference to the main form to the child form.
This is probably the most common way to solve this problem in general. When you create your child form in your main form, you'll need to pass a reference as follows:
// .. MainForm code ..
void OnGoToChildForm(object sender, EventArgs e)
{
var childForm = new ChildForm(this);
childForm.Show();
}
// .. ChildForm code ..
private MainForm mainForm; // This is where the child form will keep a reference to
// the main form that you can use later
public ChildForm(MainForm mainForm)
{
// This is the child form's constructor that we called above,
// and it's where we'll save the reference to the main form
this.mainForm = mainForm;
}
// This also needs to be the event handler for the close event
void OnBackToMainClicked(object sender, EventArgs e)
{
this.Close();
mainForm.Close();
}
3. Add an event handler on the child form's FormClosed event. This is a safe way to solve the problem if you are concerned about keeping your main application logic under the control of the main form. It's similar to the solution suggested by Lamloumi above, but it's all done in the main form's code.
// .. MainForm code ..
void OnGoToChildForm(object sender, EventArgs e)
{
var childForm = new ChildForm(this);
childForm.FormClosed += new FormClosedEventHandler(SecondForm_FormClosed);
childForm.Show();
}
void SecondForm_FormClosed(object sender, EventArgs e)
{
// Perform any final cleanup logic here.
this.Close();
}
Form1 _FirstForm = New Form1();
Form2 _SecondForm = New Form2();
MainForm _MainForm = new MainForm();
_FirstForm.Close();
_SecondForm.Close();
_MainForm.Show();
Normally , in the Home form you have some ting like this :
SecondForm second= new SecondForm ();
second.Show();
this.Hide();
In the SecondForm you must ovveride the event of closure like this :
public class SecondForm :Form{
public SecondForm()
{
InitializeComponent();
this.FormClosed += new FormClosedEventHandler(SecondForm_FormClosed);
}
void SecondForm_FormClosed(object sender, FormClosedEventArgs e)
{
Application.Exit();
}
}
To be sure that your application is closed after you close the form. because the Home from is still active and hidden if you don't.
use this in Form2
private void button1_Click(object sender, EventArgs e)
{
Form1.FromHandle(this.Handle);
}
There Handle are the same now ;
hope this work.

Removing Closed Form from a List in C#

So, i have a question on using a list of forms and when a form closes, to remove itself from the list in C#. I don't think the garbage collector does it automatically, right?
Let's say I have:
List<SomeGraphForm> GraphGroup = new List<SomeGraphForm>();
....
add the forms...
GraphGroup.Add(x);
When x closes, what is the cleanest way to remove it from the list? Is using FormClosed event the best way (but I am not sure how to pass SomeGraphForm item back to the other class(es)).
Right, the GC cannot collect something that is still referred to. I would go with this basic approach:
//code to create and add form
var form = new Form1();
form.FormClosed +=form_FormClosed;
_forms.Add(form);
form.Show();
//cleanup
private void form_FormClosed(object sender, FormClosedEventArgs e)
{
var closedForm = sender as Form1;
_forms.Remove(closedForm);
}
If you have a base class that you use to derive all forms from, you can unregister in the OnClosed method.
protected override void OnClosed(EventArgs e)
{
// unregister here
}

If Else Condition For .Close?

i got 2 forms 1mdiparent, 1child
lets say mdiparent = Form1 then child = Form2 .
i got New button in Form1 calling childform (Form2) like:
private void newDocument_ItemClick(object sender, ClickEventArgs e)
{
Form2 formChild = new Form2();
Form2.Show()
}
now my question was whats the if else condition for : if Form2 == Close?
something like:
if (Form2.Close == true){ //condition }
or if (Form2 == Close){ //condition }
but i know its not the right code .so hope you could help me :) thanks .
If I understand your question correctly, you want to be notified by the system when the Form2 is closed so you could apply some internal logic to avoid the reopening of the child form and apply some kind of changes to your main interface.
If this is your problem then you could add your event handler for the FormClosing event of the Form2 directly in the code of Form1 when you open the Form2
// Flag to keep the state open/close of the child form
private bool childClosed = true;
private void newDocument_ItemClick(object sender, ClickEventArgs e)
{
if(childClosed == true)
{
Form2 formChild = new Form2();
// Setup the event handler form the Form2 closing directly here in the MDI
formChild.FormClosing += new FormClosingEventHandler(myFormClosing);
formChild.Show();
// set the flag to avoid the reopening
childClosed = false;
}
}
// Now, when the formChild closes, you will receive the event directly here in the MDI
private void myFormClosing(object sender, FormClosingEventArgs e)
{
// The child form is closing......
// Do your update here, but first check the close reason
if(e.CloseReason == CloseReason.UserClosing)
{
......
// reset the flag so you could reopen the child if needed
childClosed = true;
}
}
You will probably want to use either the Form.FormClosed event or the Form.FormClosing event. Probably the former since you don't really want to interact with the closing of the form.
You would create a method and have it called when the event is fired and this would do whatever you wanted (such as hide buttons and such like).
See http://msdn.microsoft.com/en-us/library/system.windows.forms.form.formclosed.aspx for details of the formclosed event.
When a form is closed, it's disposed too. Thus just check if it's disposed by following code:
Form2 formChild = new Form2();
// ...
if (formChild.IsDisposed) {
// Do someting
}
As #V4Vendetta pointed out: there is a FormClosing event (called before the form has closed. Used to tell the user "You haven't saved yet") and a FormClosed event (called after the form closed).
public class Form2 : Form
{
public bool hasClosed;
private void Form2_FormClosed(object sender, FormClosedEventArgs e)
{
hasClosed = true;
}
}
with this, you can do
if (formChild.hasClosed)
// do something
It is wrong to take this approach, the Form 2 is initialized in the button click event, therefore, you assume that the form object was not available.
if you want to change this order, then the form should be initialized somewhere else like the constructor of the Form 1.
private Form2 form2;
public Form1()
{
form2 = new Form2();
}
private void newDocument_ItemClick(object sender, ClickEventArgs e)
{
if(!form2.Visible)
{
form2.Show();
}else
{
form2.Hide();
}
}
Hiding a form is not same as closing a form, if you really open and close the form2 and carry out some action based on that, then you should set a property on the parent form when the form2 closing event is triggered, to do this you must pass the parent form as an argument in the form2 constructor.
You can check that with the help of the following code
foreach (Form f in Application.OpenForms)
{
if (f.Text == formName)
{
IsOpen = true;
break;
}
}
if(!IsOpen)
{....do your code....}

How to use MdiContainer

This is what I usually do when I want to open a new form from a ToolStripMenu
private void alumnoToolStripMenuItem_Click(object sender, EventArgs e)
{
frmAlumno x = new frmAlumno();
x.ShowDialog();
}
but a teacher told me that it´s wrong because this shouldn´t happen..
So I guess I have to use MdiContainer but I´m not sure of how to write the code now... Please some help...
If you use MDI, you should call Show, not ShowDialog. Also you need to set MdiParent.
Form2 newMDIChild = new Form2();
// Set the Parent Form of the Child window.
newMDIChild.MdiParent = this;
// Display the new form.
newMDIChild.Show();
How to: Create MDI Child Forms
I'm going to answer with a solution to your actual problem instead of describing how to use MdiContainer, since you don't actually need it. :)
Forms have a ShowInTaskbar property that defaults to true. Set it to false and the form will no longer appear in the task bar.
private void alumnoToolStripMenuItem_Click(object sender, EventArgs e)
{
frmAlumno x = new frmAlumno();
x.ShowInTaskbar = false;
x.ShowDialog();
}
See MSDN for more information.
Introduction to MDI Forms with C#

Working with Forms

I'im writing a program that works with 2 forms, the main form and the form where the configuration is made, so when the user clicks toolstripmenu->Preferences the Preferences form is showned and I want it to make the user only capable of having one Preferences form at a time.
When I use:
Prefs preferencias = new Prefs;
private void preferenciasToolStripMenuItem_Click(object sender, EventArgs e)
{
preferencias.Show();
}
It works, but when I close the Preferences form and try to open a new one the program crashes.
And When I use:
private void preferenciasToolStripMenuItem_Click(object sender, EventArgs e)
{
Prefs preferencias = new Prefs;
preferencias.Show();
}
The user can hav multiple Preferences form.
What can I do?
Thanks in advance.
It sounds like you want a modal dialog, so you need to use the ShowDialog( ) method instead of Show( ):
private void preferenciasToolStripMenuItem_Click(object sender, EventArgs e)
{
preferencias.ShowDialog();
}
The ShowDialog() that others have suggested is a good answer. If you're interested in an alternative, here's something I sometimes do:
private void FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
Hide();
}
}
What this does is simply hides the form so that if you show it again, its already loaded into memory. Additionally, if you have a timer or some other thread in that form running, it can still run and do its thing.
preferencias.ShowDialog()
will only allow one preference window to be open .
You can use the Application.OpenForms property in your menu item's click event to check if a form of that type is already open. If there is no form of that type open, then you can open your instance. If there is, it simply won't show.
foreach (Form form in Application.OpenForms) {
if (form.GetType() != typeof(PreferencesForm)) {
new PreferencesForm().Show();
}
}
Or as already stated you can call PreferencesForm.ShowDialog() to make the form modal, in which case the user has to close the form before they can even interact with the main form again.
The method you use depends on if you want the user to be able to use the main form even if the preferences form is open.
If you're looking for 1 and ONLY 1, You probably want to implement the Singleton pattern for the Prefs class.

Categories