When I try to create an object of the form class within the form class, it gives an exception as stackoverflow occured.However, when I declare the object of form class within a method,it works fine.the code is as follows:
namespace WindowsFormsApplication6
{
public partial class Form1 : Form
{
**Form1 f1 = new Form1();**//gives stackoverflow exception.......
char[] ar = new char[15];
int flag = 0, end;
double val1, val2, res;
string oprt;
public Form1()
{
InitializeComponent();
}
private void masters(object sender, EventArgs e)
{
ar[i] = char.Parse(((Button)sender).Text);
if (char.IsDigit(ar[i]))
{
if (flag != 0)
{
if (textBox1.Text == oprt)
{
textBox1.Clear();
}
}
else
{
if (end == 1)
{
textBox1.Clear();
end = 0;
}
}
Button ansbox = sender as Button;
textBox1.Text += ansbox.Text;
}
else if (char.IsSymbol(ar[i]))
{
if (textBox1.TextLength != 0)
{
val1 = double.Parse(textBox1.Text);
textBox1.Clear();
Button bt = sender as Button;
if (bt != null)
textBox1.Text = bt.Text;
oprt = bt.Text;
// dot.Enabled = true;
flag = 1;
}
}
}
private void button14_Click(object sender, EventArgs e)
{
if (textBox1.TextLength != 0)
{
val2 = double.Parse(textBox1.Text);
switch (oprt)
{
case "+": res = val1 + val2;
break;
case "-": res = val1 - val2;
break;
case "*": res = val1 * val2;
break;
case "/": res = val1 / val2;
break;
}
textBox1.Text = res.ToString();
flag = 0;
end = 1;
}
}
}
}
}
Creating an instance of Form1 would cause the f1 property to be initialised with an instance of Form1 which would cause the f1 property to be initialised with an instance of Form1 which would cause the f1 property to be initialised with an instance of Form1 which would cause the f1 property to be initialised with an instance of Form1 which would cause the f1 property to be initialised with an instance of Form1 which would cause the f1 property to be initialised with an instance of Form1 which would cause the f1 property to be initialised with an instance of Form1 which would cause the f1 property to be initialised with an instance of Form1 which would cause the f1 property to be initialised with an instance of Form1 which would cause the f1 property to be initialised with an instance of Form1 which would cause the f1 property to be initialised with an instance of Form1 which would cause the f1 property to be initialised with an instance of Form1 which would cause the f1 property to be initialised with an instance of Form1 which would ... Stack Overflow!
Within a method in the class, the 'f1' would be local and only exist for the life of the call. Unless you called the same method on the instantiated Form1 then there wouldn't be subsequent Form1s created.
You're creating an private instance of Form1 when Form1 is created so this is sort of an endless loop:
Somewhere in your code you create your first Form1 instance.
When this instance is creating it creates a new instance of Form1.
This instance also creates an instance of Form1 and again, and again etc.
So when an instance is created all variables are initialized and when you declare them like this:
Form1 f1 = new Form1() this automaticly instatiates a new instance of the form.
I suggest you don't have a new instance of your Form1 inside your Form1 but if you really need this create a method to make the instance:
Change the Form1 f1 = new Form1(); into Form1 f1;.
And create a method:
public void InstantiateNewForm1Instance()
{
f1 = new Form1();
}
But: DON'T CALL THIS METHOD IN THE CONSTRUCTOR! Or else you will have the same problem :-)
That's because every time you create an instance of your class, it creates another instance of your class and so on...and so on...and so on...
In other words, you have a infinite recursion when you try to create an instance of your class.
You need to add some kind of control around whether or not a new instance of Form1 gets created at construction time. A simple (and not complete) solution would be something like:
public partial class Form1 : Form
{
Form1 f1;
public Form1() : this(false)
public Form1(bool createNewInstance)
{
if(createNewInstance)
f1 = new Form1();
else
f1 = null;
}
}
The form is instantiated, then it processes the private fields, which instantiates the form1, which then instantiates the private fields (finding form1), which then instantiates that object and processes the private fields, continuing on.
So that is why that happens, whereas, in a method, a method only executes when called, no internal initialization.
Why, when in form1, do you need another instance of the same form?
Could it be because Form1 is trying to instantiate another Form1 which in turn is trying to instantiate another Form1 etc?
If you're in the new constructor of Form1, an instance of Form1 is already being created. So, before it's finished being created, you're creating another, then that one does the same. Before your program loads, too many form1s are going on the stack...overflowing the stack.
If each Form1 class contains one new instance of a Form1 class, you are bound to have a stack overflow exception when trying to create one.
You can see it more clearly by trying to draw the objects on a sheet of paper, simulating the space they occupy in memory and the space occupied by their children - but remember, each Form 1 must be of the same size!
Related
I am trying to open ChildForms on MdiParent Form using a Form Manager Class.
I've tried several alternatives in order to tell "FormManager" Class which Form is the MdiParent; however it would always throw errors (1 different error for each different occasion).
Most of the times it would say that MainForm was not a MdiContainer; and this is not true as I had set MainForm previously as such.
Note:1 Main Form is set as a MdiContainer.
Note:2 If I attempt to open only 1 Form it will open perfectly inside MdiParent Form. However if I attempt to Load 2 or more Forms it will throw error.
Note:3 If I create the Child Forms Instances on Main Form; Everything works just fine. No issues at all. But this is not how I want to do it.
// [Class] : Main Form
// Member Variables
private FormManager FrmMgr;
// Load Forms using FormManager Class
private void Load_Forms()
{
// Create a new Instance of FormManager.
if (FrmMgr == null) { FrmMgr = new FormManager(); }
// Set MainForm as MdiParent in FormManager Class
FrmMgr.MdiParent = this;
// Alternatively Manually Set the MdiParent in MainForm (Uncomment Line Bellow)
// this.IsMdiContainer = true;
}
// [Class] : Form Manager
// <Member Variables>
private Form1 frm1;
private Form2 frm2;
// FormManager <Constructor>.
// Constructor Receives MdiParent Information from MainForm
// and Sets the MdiParent.ActiveControl Information to Every Form
// when calling each (Form initiation) Method.
public FormManager(Form _MainParent)
{
// Create new Instance of Form1
Init_Frm1(_MainParent);
// Create new Instance of Form2
Init_Frm2(_MainParent);
}
private void Init_frm1(_MainParent)
{
if (frm1 == null) { frm1 = new Form1(); }
frm1.MdiParent = _MainParent;
frm1.Show();
}
private void Init_frm2(_MainParent)
{
if (frm2 == null) { frm2 = new Form2(); }
frm2.MdiParent = _MainParent;
frm2.Show();
}
}
Can anyone point me in the right direction and help me understand why this happens?
Thanks in advance.
I was finally able to sort it out.
The issue seemed to be consisted in the way I've used to pass "MainForm" as the "MdiParent" to "FormManager" class.
// [Class] MainForm
// Create new Instance (Always Active); of FormManager Class
// Note: When FormManager Class is Loaded; it's Constructor will
// run the Methods that will open all the initial Forms.
private void Load_Modules()
{
// "this" refers to "MainForm"
if (FrmMgr == null) { FrmMgr = new FormManager(this); }
}
// [Class] FormManager
// Member Variables
private Form1 frm1;
private Form2 frm2;
// <Constructor>
public FormManager(Form _MainParent)
{
// Create new Instance of Form1 under "Init_Frm1" Method
Init_Frm1(_MainParent);
// Create new Instance of Form2 under "Init_Frm2" Method
Init_Frm2(_MainParent);
}
// Method that Will Create new Instance of Form1
private void Init_Frm1(Form _MainParent)
{
if (frm1 == null) { frm1 = new Form1(); }
frm1.MdiParent = _MainParent;
frm1.Show();
}
// Method that Will Create new Instance of Form2
private void Init_Frm2(Form _MainParent)
{
if (frm2 == null) { frm2 = new Form2(); }
frm2.MdiParent = _MainParent;
frm2.Show();
}
I have Form1 where I want to use the list of objects listaPacienti I created in Form2 but it doesn't work.
Pacient is the class used to generate objects.
Here is Form1's beginning:
public partial class Form1 : Form
{
Form2 formPacienti = new Form2();
List<Pacient> listaPacienti = new List<Pacient>();
public Form1()
{
InitializeComponent();
}
And here is the beginning of Form2 where I created the list listaPacienti I want to pass to Form1:
public partial class Form2 : Form
{
List<Pacient>listaPacienti=new List<Pacient>();
Pacient p1 = new Pacient(0, "Pacient1", 0, 200);
Pacient p2 = new Pacient(1, "Pacienct2", 0, 100);
Form1 formMedici = new Form1(listaPacienti);
public Form2()
{
InitializeComponent();
listaPacienti.Add(p1);
listaPacienti.Add(p2);
}
What's wrong because I searched here before and that's how it is recommended to be done and if I wrote something wrong I don't know what it is because in Form2, the parameter "listaPacienti" from the following line
Form1 formMedici = new Form1(listaPacienti);
shows me this message: "A field initializer cannot reference the non-static field, method or property "Form2.listaPacienti".
Thank you
There are several things wrong here actually. The error itself is telling you that you can't use a class member when initializing a class member. You're trying to use listaPacienti to initialize formMedici. But you could initialize it in the constructor. Something like this:
List<Pacient> listaPacienti = new List<Pacient>();
Pacient p1 = new Pacient(0, "Pacient1", 0, 200);
Pacient p2 = new Pacient(1, "Pacienct2", 0, 100);
Form1 formMedici;
public Form2()
{
InitializeComponent();
listaPacienti.Add(p1);
listaPacienti.Add(p2);
formMedici = new Form1(listaPacienti);
}
However, your Form1 constructor also needs to accept that parameter. So you either need to modify the existing Form1 constructor or add a new one:
public Form1(List<Pacient> listaPacienti)
{
InitializeComponent();
// do something with listaPacienti?
}
However, it's not really clear why you're even doing this. You create an instance of Form2 in Form1:
Form2 formPacienti = new Form2();
Then you create an instance of Form1 in Form2:
Form1 formMedici = new Form1(listaPacienti);
This is an infinite recursion waiting to happen. Do you really want Form2 to create a new instance of Form1? Or do you want to use the existing instance of Form1? If the latter, then remove the references to Form1 entirely from Form2.
There are a variety of ways to accomplish the overall goal of what you're trying to do, and which one is ideal depends on more than what's presented here. But the simplest approach given the information present is probably to just make listaPacienti accessible from outside of Form2:
public List<Pacient> ListaPacienti { get; set; }
Pacient p1 = new Pacient(0, "Pacient1", 0, 200);
Pacient p2 = new Pacient(1, "Pacienct2", 0, 100);
public Form2()
{
InitializeComponent();
ListaPacienti = new List<Pacient>()
ListaPacienti.Add(p1);
ListaPacienti.Add(p2);
}
Now that listaPacienti is a public property, any code which has a reference to an instance of Form2 can access that property:
Form2 formPacienti = new Form2();
// Do other things with formPacienti?
// Either way, here you can access formPacienti.ListaPacienti
You need to add one more constructor to form one like this.
public Form1(List<Pacient> list)
{
this.listaPacienti=list;
InitializeComponent();
}
After that you can go with this code as you are going.
Form1 formMedici = new Form1(listaPacienti);
Move the instantiation of Form1 and listaPacienti into the constructor. This existing answer provides a good description of why you are getting this error - A field initializer cannot reference the nonstatic field, method, or property.
public partial class Form2 : Form
{
List<Pacient>listaPacienti;
Pacient p1 = new Pacient(0, "Pacient1", 0, 200);
Pacient p2 = new Pacient(1, "Pacienct2", 0, 100);
Form1 formMedici;
public Form2()
{
listaPacienti=new List<Pacient>();
formMedici = new Form1(listaPacienti);
InitializeComponent();
listaPacienti.Add(p1);
listaPacienti.Add(p2);
}
}
You can do the following
Sender Form:
private void btnIniciar_Click(object sender, EventArgs e)
{
this.Hide();
Main newMain = new Main(this.lsProcesos);
newMain.ShowDialog();
this.Show();
}
Receiver Form:
public partial class Main : Form
{
List<Proceso> lsProcesos;
public Main(object sender)
{
InitializeComponent();
lsProcesos = (List<Proceso>)sender;
}
}
How can I change this code so the label's text changes. Between this..Controls there was an MdiParent but I don't have one.
private void KeyOfficial_Load(object sender, EventArgs e)
{
label2.Text = "Login as: " + ((Form)this..Controls["label1"]).Text;
}
When you initialize KeyOfficial you could submit an reference to your main form like this:
MainForm MainFormRef;
public KeyOfficial(MainForm mainRef)
{
this.MainFormRef = mainRef;
}
In Main Form you initialize like this:
KeyOfficial koForm = new KeyOfficial(this);
And the reference is set.
Now you can reach the lable1:
label2.Text = "Login as: " + this.MainFormRef.label1.Text;
Here you can use this to get the instance of the MainForm whenever you want to access its fields
public static MainForm instance=null;
public static MainForm GetInstance()
{
if (instance != null)
{
return instance;
}
else
{
instance = new MainForm();
return instance;
}
}
Place this code in MainForm.cs and then call this function whenever you want to access that field directly like,
MainForm.GetInstance().<field_name>
I have used the similar things in my app when I need to access different fields from one form to another and its working fine for me.
This is my form 2, this is where the checkboxes are.
My operator in here which is on the middle, has a random character generator, which my code is this :
char[] select = new char[] { '+', '-', '/', '%', '*' };
var rand = new Random();
char num = select[rand.Next(5)];
lbloperator.Text = Convert.ToString(num);
If the only check is addition, my form 1 will only perform addition, or if add,subtract, my form 1 will only perform add and subtract. Please help me with this! :(
FORM1
There is tow ways to do that:
1- first way is define public property in form2 that can tell form1 the status of checkBox1:
Form2:
public bool MyCheckBoxStatus
{
get {return checkBox1.Checked;}
}
Form 1 (For Example):
Form2 frm = new Form2;
frm.ShowDialog();
if (frm.MyCheckBoxStatus)
{
//Do something...
}
2- The other way: if you are using Windows Forms Application then all your controls have a property named Modifiers change its value to public and write this code in Form1:
Form2 frm = new Form2;
frm.ShowDialog();
if (frm.checkBox1.Checked)
{
//Do something...
}
Try this:
public partial class Form2: Form
{
public string checkBoxSelected = "";
}
public partial class Form1 : Form
{
private void MakeResult()
{
Form2 result = new Form2();
result.checkBoxSelected = "+";
result.Show();
}
}
I'm not too sure exactly what you are asking, but it sounds like you are trying to pass some data between forms.
In Form2, you can add a public property that reads your label
public string TheOperator {
get { return lblOperator.Text; }
}
Then from Form1, you can create a new instance of form2 and then reference the Property when needed.
Form2 fm = new Form2();
fm.Show();
string theOp = fm.TheOperator;
//////////
In response to your edit:
You can add this to Form1, exposing the operator variable there:
public string MyOperator {
get { return lblOperator.Text; }
set {
lblOperator.text = value;
//You can perform any updates to
//your calculations here, or call
//another method to do so
}
}
private void OpenForm2()
{
Form2 frm2 = new Form2(this);
frm2.Show();
}
Then inside of Form2, you pass a reference to Form1 so that you can access the public property:
private Form1 frm;
public New(Form1 _frm)
{
frm = _frm;
}
private void UpdateOperator()
{
//call this method, calculating your operator and then
//set the operator on the first form (variable frm) to
//What you need it to do
frm.MyOperator = lblOperator.Text;
}
Let's say, I have 2 WinForms here, Form1 and Form2 respectively. And then I made Form1 hidden. I wonder how I could write the code in Form2 to detect if Form1 object is still running or not.
I was trying to use Form1.ActiveForm but it seems to give me NULL value. Any better ideas? Thanks.
You could use my method to get any active forms:
public static Form IsFormAlreadyOpen(Type FormType)
{
foreach (Form OpenForm in Application.OpenForms)
{
if (OpenForm.GetType() == FormType)
return OpenForm;
}
return null;
}
If you mean by running "is still in memory" then you could
simply test the reference to the form: if(form1 != null)
after that you could test for being hidden: if(form1.Visible)
and possibly minimized: if(form1.WindowState != FormWindowState.Minimized)
If you want to check whether your form has been closed (and therefore disposed) you can try calling a method from that form and catching the ObjectDisposedException.
try
{
Form1.SomeMethod();
}
catch (ObjectDisposedException ex)
{
// Form has been closed
}
If the form hasn't been closed, and you want to check whether it's visible or not, you can use it's "Visible" property
It looks to me that you are trying to access Form1 as a static instance and unless you have created Form1 in this manner you will not be able to access it and this could be why you are getting NULL values from your function. If you want to reference Form1 from Form2 then you need to pass it a reference.
Form1:
public class Form1
{
public Form1()
{
}
}
Form2:
public class Form2
{
private Form1 _frm1;
public Form2(Form1 frm1)
{
_frm1 = frm1;
}
}
Now when you create your instance of Form2 you declare it like...
Form2 frm2 = new Form2(frm1);
Where frm1 is the instance of Form1.
Now whenever you need to refer to Form1 from Form2 you can refer to it via _frm1.
private Form GetForm()
{
Form mdiParent = this.MdiParent;
Form1 objForm
foreach (Form frm in mdiParent.MdiChildren)
{
objForm = frm as Form1;
if (objForm != null)
{
objForm.Activate();
return objForm;
}
}
return null;
}