I have 2 windows forms; Form1.cs and Form2.cs.
Here are the code for Form1.cs in which will show the Form2.cs and Hide the the current Form1.cs
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.Show();
this.Hide();
}
Here are the code for Form2.cs in which will show the Form1.cs and Hide the the current Form2.cs
private void button1_Click(object sender, EventArgs e)
{
Form2 f2 = new Form2();
f2.Show();
this.Hide();
}
I have monitored the memory usage of the application and I have noticed that the memory usage of the application is increasing every time I execute the code above.
You're creating new forms on each button click, so you hold many instances in memory after clicking the buttons multiple times.
You're probably looking for this.Close() instead of this.Hide(), as the former will close and dispose the current form while the latter will only hide it.
If you want to hide and re-show the forms, you need to keep a reference to the forms. There are a lot of considerations (should a form be instantiated only once, or each time it is requested? Should it be possible for multiple instances of the same form be opened? And so on) and possible patterns and (third-party) solutions (e.g. Application Controller, What is a proper way of building Winform apps with multiple “screens”).
One solution would be to simply create your own form registry where each form has a singleton:
public static class FormRegistry
{
private static Lazy<Form1> _form1 = new Lazy<Form1>(() => new Form1());
public static Form1 Form1
{
get
{
return _form1.Value;
}
}
private static Lazy<Form2> _form2 = new Lazy<Form2>(() => new Form2());
public static Form2 Form2
{
get
{
return _form2.Value;
}
}
}
Then anywhere in code, you can just do FormRegistry.Form1.Show(). Please note this code is a proof of concept with many issues and much room for improvement, but it's there to give you the general idea.
Related
I am trying to open a single form at once. If user tries to open another form while one form is already open it should not open it.
my code :
else if (instrument_name == "Micrometer")
{
this.Hide();
Form2 f2 = new Form2();
f2.ShowDialog();
this.readclose()
}
here only if this form is not opened already then form 2 is opened.
the solution could be :
Form fc = Application.OpenForms["UpdateWindow"];
if (fc != null)
fc.Close();
fm.Show();
but I don't know where should I write this because if I put this Form1_Load then obviously it will not contain null even for the first time.
Should I put this in program file?
You can create smth like 'form manager', which will monitor all opened forms.
In situation when form is close the manager opens it, otherwise reopen it.
This solution is similar to your, but in this case all logic is concentrated in one place and easy to understand or maintenance it.
You can do it different ways. But one of it is to implement a singletone pattern. For that you have to modify your Form2 the following way:
public partial class Form2 : Form
{
private static Form2 Instance;
private Form2()
{
InitializeComponent();
}
public static Form2 GetForm2Instance()
{
if(Instance==null) Instance = new Form2();
return Instance;
}
public static void CloseOldForm2AndOpenNewForm2()
{
if (Instance != null) Instance.Close();
Instance = new Form2();
Instance.Show();
}
private void Form2_FormClosed(object sender, FormClosedEventArgs e)
{
Instance = null;
}
}
As you can see the Form2() is private. In order to load form you have to use the following code:
//Case 1 if you porefer to use existing instance of the Form2
Form2 myForm = Form2.GetForm2Instance();
myForm.Show();
//Case 2 if you prefer to close old one and create a new Form2
Form2.CloseOldForm2AndOpenNewForm2()
This question already has answers here:
Communicate between two windows forms in C#
(12 answers)
Closed 3 years ago.
First off I know there have been similar Q&A for this. I haven't seem to have found the answer I am looking for, but it's possible I missed it. Second I am new to the C# language as I've mostly worked in C++ so please forgive me if this is a stupid question.
A little background now on what I am trying to accomplish. I'm in the process of making a Paint application. The first form, Form1 as I'll call it is where all of the UI is for my application and where the user will draw. I want to allow the user to select different brush types and sizes. On Form1 I have a button which the user will click to change these options. When this button is clicked it will initiate what I'll call Form2. Form2 will have the options for brush type and size and when the user selects them and hits the OK button the size and brush type should be passed back. I am just using two int variables to hold the brush type and the brush size to keep things simple since Form1 needs to know this, not Form2.
All of the information I have found is for passing information from Form1 to Form2, when I really want to pass information from Form2 to Form1. Is there a simple way to do this? I will be passing information like this for several other buttons as well so I am hoping not to over complicate things.
Thank you very much for your time!!! :)
This is in Form1 which calls Form2
private void brushBtn_Click(object sender, EventArgs e)
{
//New form which will ask which brush type and the size
Form2 paintInfo = new Form2() ;
paintInfo.ShowDialog();
}
This is Form2
public partial class Form2: Form
{
public Form2()
{
InitializeComponent();
}
int typeOfBrush;
//User picked the circle brush
private void circleBrushBtn_Click(object sender, EventArgs e)
{
typeOfBrush = 1 ;
}
//User picked the square brush
private void squareBrushBtn_Click(object sender, EventArgs e)
{
typeOfBrush = 2 ;
}
private void okBtn_Click(object sender, EventArgs e)
{
//PASS THE BRUSH TYPE & SIZE BACK TO FORM1 WHEN USER HITS OK BUTTON
this.Close() ;
}
}
Usually this kind of program has a tool palette that contains the various tools.
The palette is non modal, meaning that you don't block the execution of code in the first form when you show the palette. It stays in some corner and you click over the icons in the palette to change your behavior.
But, if this is the case, then passing back information to form1 requires a delegate and an event handler
So, inside Form2 code you have
public enum ToolEnum
{
Draw = 1,
Rubber = 2,
Fill = 3,
......
}
public class Form2
{
public delegate void OnToolChanged(ToolEnum newTool);
public event OnToolChanged ToolChanged;
....
protected override palette_Click(object sender, EventArgs e)
{
// Code that retrieves the tool clicked....
ToolEnum choosenTool = GetTool();
// If someone is interested to know when the user changes tool
// then it has subscribed to the ToolChanged event passing an
// appropriate event handler
if(ToolChanged != null)
ToolChanged(choosenTool);
}
}
The form1 call the form2 in this way
// Open the form with the palette passing reference to this instance of form1.
// Important to link the two forms together....
Form2 f = new Form2(this);
// Now inform the form2 instance that this instance of form1
// wants to know when the user clicks another tool
f.ToolChanged += myToolChangedHandler;
....
// We receive here the notification of the click event on the palette form
public void myToolChangedHandler(ToolEnum newTool)
{
if(newTool == ToolEnum.Fill)
{
... adapt for the fill operation ...
}
}
EDIT
However, if you want the follow the simpler road of showing modally your Form2, then the code is easy
private void brushBtn_Click(object sender, EventArgs e)
{
//New form which will ask which brush type and the size
using(Form2 paintInfo = new Form2())
{
paintInfo.ShowDialog();
int brushType = paintInfo.BrushType;
}
}
....
public partial class Form2: Form
{
public Form2()
{
InitializeComponent();
}
int typeOfBrush;
public int BrushType
{
get {return typeOfBrush;}
set {typeOfBrush = value;}
}
private void circleBrushBtn_Click(object sender, EventArgs e)
{
this.BrushType = 1 ;
}
}
Don't overthink this. A form is just an object. From within Form1 you will create a new object of type Form2. Form2 can have whatever properties (two ints in your case) that can be set however you wish. Assuming you are using WinForms, you will probably want to show Form2 via ShowDialog() which is a blocking call. When ShowDialog() returns, you can then interrogate Form2 (you still have a handle to the object in Form1) about any of its properties.
If this is not enough to get you started, I'm sure someone else will post an entire coded solution.
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.
private void button1_Click(object sender, EventArgs e)
{
Form2.Show();
}
I have the code above which in my opinion contains no error but it won't execute by some reason.
It says the error "An object reference is required for the non-static field, method, or property" but what I have missed?
I have just two forms (Form1 and Form2) and one button nothing more. I used a registry cleaner but the error persists.
There exists another code for it which worked, but this code makes a copy of my form as a new variable, but I would like to show the original form like it Visual Basic did.
In addition to storing a reference to your Form at Class level, you need to check if it has been closed since the last time it was used. In that case you'd need to create a new instance (just as you do for the very first use). The below example also restores the form if it was minimized:
public partial class Form1 : Form
{
Form2 F2 = null;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (F2 == null || F2.IsDisposed)
{
F2 = new Form2();
F2.Show();
}
else
{
if (F2.WindowState == FormWindowState.Minimized)
{
F2.WindowState = FormWindowState.Normal;
}
F2.Activate();
}
}
}
Form2 or Form1 are just a names of classes. Before using of this classes you need to create an instance of them
Form2 secondaryForm = new Form2();
After this you can use all methods and properties of that class secondaryForm.Show();
So before using/showing your Form2, you need to create an instance. If you want show
your original form
, meens that instance are already created. You need check your code where that instance was created and put reference to that form in variable:
Create a variable in Form1:
private Form2 secondaryForm;
In code where you created already your original Form2 just use this variable:
this.secondaryForm = new Form2();
After this anywhere in Form1's code you can show a Form2 with next line:
this.secondaryFomr.Show();
Methods opening forms :
form1 --> form2 --> form3
ChecklistBox on the form1 there. How to know the form3 That is active or not?
If the forms you are referencing are MDI child forms, you could use
Form activeChild = this.ActiveMdiChild;
else you could use the following code if not using MDI child forms.
Form currentForm = Form.ActiveForm;
I understand that you are asking if form 3 is opened. If that is incorrect, please enlighten me.
There are probably dozens of ways to do so, it all depends on what you want to do.
One simple way would be to leave a flag somewhere, say in your Program.cs file:
public static bool Form3IsOpen = false;
Then:
private void Form3_Load(sender object, EventArgs e)
{
Program.Form3IsOpen = true;
}
And:
private void Form3_Close(sender object, EventArgs e)
{
Program.Form3IsOpen = false;
}
Supplemental:
You can also keep a reference to your subform:
In form1.cs:
private Form2 FormChild;
//In the function that opens the Form2:
FormChild = new Form2();
FormChild.Show();
Form2 will have something similar to retain Form3. If one form can open several, just use an array or collection.
When i usually have many different forms and only one instance to be created, i put them in dictonary and check it if there is a form.
Something like this:
public static Dictonary<string, Form> act_forms_in_app = new Dictonary<string, Form>();
now in every forms creation i do it like this
Form1 frm = new Form1();
frm.Name = "Myformname"
//set its properties etc.
frm.Load => (s,ev) { act_forms_in_app.Add(frm.Name, frm);};
frm.Load += new EventHandler(frm_Load);
frm.Disposed => (s, ev) { act_forms_in_app.Remove(frm.Name)};
//your usual form load event handler
public void frm_Load(object sender, EventArguments e)
{
...
}
somewhere where you want to check
Form frm = //Your form object
if(act_forms_in_app.ContainsKey(frm.Name))
{
//Perform as required
}