System.StackOverflowException when switching between forms - c#

I am trying to create a menu for a game I' m developing. This is the source code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Racing_Manager
{
public partial class Form1 : Form
{
Form1 form1 = new Form1();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
}
//Exit Button
private void button1_Click(object sender, EventArgs e)
{
Application.Exit();
}
//Help Button
private void Help_Click(object sender, EventArgs e)
{
}
//Play Button
private void Play_Click(object sender, EventArgs e)
{
Hide();
Form2 secondMenu = new Form2();
secondMenu.Show();
}
}
}
Then I have:
namespace Racing_Manager
{
public partial class Form2 : Form
{
public Form2 form2 = new Form2();
public Form2()
{
InitializeComponent();
}
//Back Button
private void button2_Click(object sender, EventArgs e)
{
Hide();
Form1 form1 = new Form1();
form1.Show();
}
}
}
When I run this, it gives a System.StackOverflowException (I know, quite appropriate) on this line:
Form1 form1 = new Form1();
What am I doing wrong? How do I fix it? Anything I can do to improve the code quality?

Your problem is in the first lines:
public partial class Form1 : Form
{
Form1 form1 = new Form1();
What should this line do?
When you create an instance of Form1 it's members are initialized. Here you declared a member form1 that is initialized by creating a new instance of Form1.
When you create an instance of Form1 it's members are initialized. Here you declared a member form1 that is initialized by creating a new instance of Form1.
When you create an instance of Form1 it's members are initialized. Here you declared a member form1 that is initialized by creating a new instance of Form1.
When you create an instance of Form1 it's members are initialized. Here you declared a member form1 that is initialized by creating a new instance of Form1.
When you create an instance of Form1 it's members are initialized. Here you declared a member form1 that is initialized by CREATING A NEW INSTANCE OF Form1.
StackOverflowException
because you recursivly call the constructor of Form1 and so your call stack eventually runs full.
The same goes for Form2.
Conclusion: remove this line from your Form1 class (and the one from Form2), you don't need it anyway.

It's the very first line that's wrong:
public partial class Form1 : Form {
Form1 form1 = new Form1(); // <- this one
You're creating Form1 instance, but Form1 should initialize Form1 form1 field, which in turn creates Form1 instance with its own Form1 form1 to be initialized...

You have a property Form1 inside your Form1 class. It cause an infinite loop.
So you should change :
public partial class Form1 : Form
{
Form1 form1 = new Form1();
public Form1()
{
InitializeComponent();
}...
to
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}...

As the other answer state, Form1 and Form2 both create an instance of themselves when a new instance is constructed. It looks like you want a singleton. To achieve this change your code like so
//From
public Form1 = new Form1()
//To
public static Form1 = new Form1();
This will create an instance of the Form as soon as the Form1 class is referenced for the first time. So Form1.Form1 would automatically create a single instance.

Related

How do I expose a control's property publicly?

I want to expose the Text property of a textbox on Form1 to Form2 so Form2 can set the text in the textbox on Form1. I've read how to do it but it doesn't work so I must be doing something wrong.
Here's the code for Form1 including the declaration of the public property (TextInputText is the property, txtInput is the textbox):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public string TextInputText
{
get => txtInput.Text;
set => txtInput.Text = value;
}
public Form1()
{
InitializeComponent();
}
private void txtInput_KeyDown(object sender, KeyEventArgs e)
{
// If enter is pressed clear the textbox, but update() the history first
if (e.KeyCode == Keys.Enter)
{
TextHistory.Update(txtInput.Text);
txtInput.Text = "";
}
}
private void HistoryButton_Click(object sender, EventArgs e)
{
Form2 HistoryForm = new Form2();
HistoryForm.Show();
}
}
}
The problem is Form2 still can't see the property, or I don't know how to access it, what am I doing wrong?
Either inject Form2 with a reference to Form1 when you create it:
private void HistoryButton_Click(object sender, EventArgs e)
{
Form2 HistoryForm = new Form2(this);
HistoryForm.Show();
}
This requires you to define a custom constructor in Form2 that accepts a Form1 reference. You can then use this reference to access the property:
private readonly Form1 _form1;
public Form2(Form1 form1)
{
InitializeComponent();
_form1 = form1;
string text = _form1.TextInputText;
}
Another approach is to use the Application.OpenForms property to get a reference to Form1 in Form2:
var form1 = Application.OpenForms.OfType<Form1>().FirstOrDefault();
string text = form1.TextInputText;
You do not give Form2 a reference to the Form1 instance:
Form2 HistoryForm = new Form2();
How could you access a Instance Function, Property or Value, without a Instance? A static property would not make sense. So the most likely option is to give Form2 a constructor that takes a Form1 reference as Argument. Store that reference somewhere in Form2. Then call the constructor like this:
Form2 HistoryForm = new Form2(this);

How to get access to parent form?

I have two Windows Form in project C#.
public partial class Form1 : Form
{
public void add(){
//
}
}
public partial class FormAdd : Form
{
//
}
In Form1 after button click I open FormAdd:
var form = new FormAdd();
form.Show();
After in FormAdd I try to call parent method add:
Form1 f = new Form1();
f.add();
But I can not get access to any methods and properties of parent form.
I get error:
One approach is to pass Form1 in as the Owner of your FormAdd instance in the Show() call:
public partial class Form1 : Form
{
private void button1_Click_1(object sender, EventArgs e)
{
var form = new FormAdd();
form.Show(this); // pass this instance of Form1 in as the Owner of our FormAdd instance
}
}
Now, over in FormAdd, cast the Owner property to Form1 and call add():
public partial class FormAdd : Form
{
private void button1_Click(object sender, EventArgs e)
{
if (this.Owner is Form1)
{
Form1 f1 = (Form1)this.Owner;
f1.add();
}
}
}
Based on your picture, try to add the code above one bracket. Since the error seems to be on the scope of your condition.
This should look like this:
else
position = 0;
//{ <-- Remove this and put it below
if (this.Owner is Form1)
{
//TODO:
}
} //This should be here
Everything should compile properly after that.

Remove last item in datagridview with another form C# [duplicate]

I have two forms. First, Form1 has a group box, some labels and a listbox. I press a button and new Form2 is opened and contains some text. I want to transfer the text in Form2 to the listbox in the Form1.
So far, what I have done is make modifier of listbox to public and then put this code in the button of Form2
Form1 frm = new Form1();
frm.ListBox.items.Add(textBox.Text);
But amazingly, this does not add any value. I thought I was mistaken with the insertion so I made the same procedure. This time, I made a label public and added textbox value to its Text property but it failed.
Any ideas?
Try adding a parameter to the constructor of the second form (in your example, Form1) and passing the value that way. Once InitializeComponent() is called you can then add the parameter to the listbox as a choice.
public Form1(String customItem)
{
InitializeComponent();
this.myListBox.Items.Add(customItem);
}
// In the original form's code:
Form1 frm = new Form1(this.textBox.Text);
Let's assume Form1 calls Form2. Please look at the code:
Form1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm = new Form2();
frm.Show();
frm.VisibleChanged += formVisibleChanged;
}
private void formVisibleChanged(object sender, EventArgs e)
{
Form2 frm = (Form2)sender;
if (!frm.Visible)
{
this.listBox1.Items.Add(frm.ReturnText);
frm.Dispose();
}
}
}
Form2:
public partial class Form2 : Form
{
public string ReturnText { get; set; }
public Form2()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
this.ReturnText = this.textBox1.Text;
this.Visible = false;
}
}
The answer is to declare public property on Form2 and when form gets hidden. Access the same instance and retrieve the value.
Below code working perfect on my machine.
private void button1_Click(object sender, EventArgs e)
{
Form1 f1 = new Form1();
f1.listBox1.Items.Add(textBox1.Text );//ListBox1 : Modifier property made public
f1.ShowDialog();
}
Ok, If you are Calling Sequence is like, Form1->Form2 and Form2 updates the value of Form1 then you have to use ParentForm() or Delegate to update the previous form.
Form1 frm = new Form1();
frm is now a new instance of class Form1.
frm does not refer to the original instance of Form1 that was displayed to the user.
One solution is, when creating the instance of Form2, pass it a reference to your current instance of Form1.
Please avoid the concept of making any public members like you said
>>i have done is make modifier of listbox to public and then in form2 in button code<<
this is not a good practice,on the other hand the good one is in Brad Christie's Post,I hope you got it.
This code will be inside the form containing myListBox probably inside a button click handler.
Form2 frm2 = new Form2();
frm2.ShowDialog();
this.myListBox.Items.Add(frm2.myTextBox.Text);
frm2.Dispose();

How to select 2 Form as parameters in a form in c#

I have a method in a class that take 2 parameters like this:
public static void ShowSelectedFeeds(Form1 frm, Form2 frm2)
{
//Some code here.
}
but I don't know how to recall it in a form,
I recall methods whit 1 parameters like this:
for example the Selectoin_method is in DbCon Class and take 1 parameter Form1 frm
in Form1_Load:
DbCon.Selection_method(this)
but when it's come to a method that take 2 parameters and I want to recall it in a Fome2_Load I use this code but it doesn't work(Shows NO exception or error, nothing happen at all)
private void AddFeedsbtn_Click(object sender, EventArgs e)
{
Form1 frm = new Form1();
DBConnection.ShowSelectedFeeds(frm, this);
}
what should I do?
The easiest way is to create aForm1 variable inside Form2 and set it in the constructor of Form2. Like:
public partial class Form2 : Form
{
Form1 form1;
public Form2(Form1 form)
{
InitializeComponent();
form1 = form;
}
}
So when you create a Form2 you should pass a Form1 instance in the constructor.
private void AddFeedbtn_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2(this);// <--- Form1 instance
frm2.StartPosition = FormStartPosition.CenterScreen;
frm2.ShowDialog();
}
And then you can pass the form1 variable in the method.
private void AddFeedsbtn_Click(object sender, EventArgs e)
{
DBConnection.ShowSelectedFeeds(form1, this);
}

How to call a function from another form

this is probably one of the most common question out there, having a FORM1 and FORM2, how I can call a function (on FORM1) like: MySQLConnect from FORM2. I tried couple of options and I can't get it to work, in the second attempt I tried calling the function from a button, but no luck.
Form1.cs (My first attempt:)
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
Form2 form2 = new Form2(this);
}
public void MySQLConnect(object sender, EventArgs e)
{
// Starting a MySQL connection
}
}
Form2.cs (My first attempt:)
public partial class Form2 : Form
{
Form1 mainForm;
public Form2(Form1 mainForm)
{
InitializeComponent();
this.mainForm = mainForm;
// call function on form1 MySQLConnect()
mainForm.MySQLConnect();
}
}
Form1.cs (My Second attempt:)
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void MySQLConnect(object sender, EventArgs e)
{
// Starting a MySQL connection
}
}
Form2.cs (My Second attempt:)
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void btnMySQLConnect(object sender, EventArgs e)
{
Form1 myForm1 = new Form1();
myForm1.MySQLConnect(sender, e);
}
}
Please help!
Your first example works if you pass the parameters expected by MySqlConnect.
public partial class Form2 : Form
{
Form1 mainForm;
public Form2(Form1 mainForm)
{
InitializeComponent();
this.mainForm = mainForm;
mainForm.MySQLConnect(this, new EventArgs());
}
}
However, I can't imagine what a function named MySqlConnect could do with the parameters passed.
So it is better to remove them in the method definition and do not pass anything when you call it.
And I agree with the comments above. Why do you hide such important (and often required functionality) inside a Form instance? You have to pass this form instance everywhere you need to connect to your database. It is better to prepare some static service class ( in a Database Access Layer) that carry on this job
mainForm.MySQLConnect();
public void MySQLConnect(object sender, EventArgs e)
Any ideas? You just omitted arguments.

Categories