StackOverFlow exception, need a way around infinite loop - c#

I am making an app for a friend, and need the user to "input" a value, and return it to the MySQL code I have. this way, what displays will change.
My problem is this: When I do "Form1 newForm = new Form1();" (this is called in DB_Application)
I get a stackoverflow error.
public partial class Form1
{
private DBApplication DB_App = new DBApplication();
private void InitializeComponent()
{
this.orderID.Text = "";
this.orderID.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.EnterKey);
.....
this.phoneNumber.Text = DB_App.phone_number;
.....
}
}
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void EnterKey(object o, KeyPressEventArgs e)
{
if(e.KeyChar == (char)Keys.Enter)
{
//converts the "orderID.Text" to an integer value.
if (!int.TryParse(orderID.Text, out newCurrentID))
MessageBox.Show("not a number");
e.Handled = true;
}
}
}
public class DBApplication : DBInfo
{
Form1 newForm = new Form1(); // infinite loop
public DBApplication()
{
OrderID();
}
private string OrderID ()
{
.... //reads the MySQL info, and outputs the value from the database.
}
}
After the User presses "enter" I need the value to go back into "DB_Application" so the MySQL command may receive it, and output a new value.

As mentioned in your comments and by others, the stack overflow is coming from your DBApplication instantiating a Form1, which in turn instantiates a DBApplication, which in turn instantiates a Form1 and so on.
Rewrite your DBApplication to take a Form1 as part of its constructor rather than instantiating its own, this will avoid the infinite recursion and likely this is want you want since the DBApplication will properly reference the open form:
public class DBApplication
{
private Form1 Form;
public DBApplication(Form1 form)
{
this.Form = form;
}
...
}
public partial class Form1 : Form
{
private DBApplication DB_App;
public Form1()
{
DB_App = new DBApplication(this);
InitializeComponent();
}
...
}
Depending on the rest of your application, you may want to instantiate DB_App after the call to InitializeComponent(). (On second look at your code, it's pretty obvious that the DB_App needs to be assigned before calling InitializeComponent().)
Also, since we don't know the full design/usage of DBApplication, perhaps you need to flip it around where the DBApplication instantiates a Form1, and the Form1 has the existing DBApplication passed in instead.
There are generally better ways of doing this (say via dependency injection), but this should be a simple way without completely breaking the architecture you have now.

If you indeed call new Form1() from DBApplication the StackOverflow comes from new DBApplication() in Form1 (it's an instance variable). How to solve the problem depends on your application logic.

Related

Why I can't Invoke from a different class?

My problem is, I can't invoke a message into the TextBox and I can't understand why.
There is a main class and a second class, both with call to the other one.
Where is my error?
using System;
using System.Windows.Forms;
namespace Class_Test___Invoke
{
public partial class MAINFORM : Form
{
public MAINFORM()
{
InitializeComponent();
_INVOKER = this;
}
private MAINFORM _INVOKER;
private static CLASS _CLASS = new CLASS();
private void button1_Click(object sender, EventArgs e)
{
_CLASS._MESSENGER();
}
public void _LOGGING(string _MESSAGE)
{
if (InvokeRequired)
{
_INVOKER.Invoke(new Action<string>(_LOGGING), new object[] { _MESSAGE });
textBox_ausgabe.AppendText(_MESSAGE);
return;
}
else textBox_ausgabe.AppendText(_MESSAGE);
}
}
}
namespace Class_Test___Invoke
{
class CLASS
{
private MAINFORM _MAINFORM = new MAINFORM();
public void _MESSENGER()
{
_MAINFORM._LOGGING("Test");
}
}
}
You are assuming that the _MAINFORM you create in the CLASS constructor is the same instance as the form where the button was clicked, which is not the case. You have a chicken-and-egg problem. Your form creates a CLASS, and the CLASS creates a form. So now you have two different forms. (or two different CLASS instances since you don't show how the first form or CLASS is created)
You need to "connect" the form and the class, either by passing the form to the constructor as a parameter or by some other means.
Finally, I would encourage you to do some research on best practices for class and member names. It's a bit disconcerting for a seasoned C# developer to see names in all caps and prefaced by underscores.

Object reference not set to an instance of an object? But it is? C# [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
Newbie coder here. Working on a game of Yahtzee but can't figure out why I'm getting this error (object reference not set to instance of object) when I have corrected it already. My 'form' object is null even though I've declared an instance of it in the class constructor and a green line saying it is not being used appears.
public partial class Form1: Form {
public Form1() {
InitializeComponent();
}
private Game game;
public void ShowMessage(string message) {
lblMessage.Text = message;
}
public void StartNewGame() {
game = new Game(this);
}
private void btnRoll_Click(object sender, EventArgs e) {
game.RollDice();
}
class Game {
private Form1 form;
public Game(Form1 form) {
form = new Form1();
}
public void RollDice() {
form.ShowMessage("blahblah");
}
The "NullReferenceException" error appears over form.ShowMessage and I don't know why. I have declared a new instance of the form class in the game constructor which is run when the player selects StartNewGame which runs the StartNewGame method. The easiest way to get it working is to simply add "Form1 form" to the parameter of the RollDice() method in the Game class, and then game.RollDice(this) in the Form1 event handler. But the instruction guide for the assignment states that we shouldn't do that and we are to initialize the Form1 object in the constructor of Game. Please help I'm new and cant understand why this is happening.
Your problem is a naming conflict in your constructor:
public Game(Form1 form)
{
form = new Form1();
}
The parameter has the same name as the form level variable. This means the constructor code is newing up the variable you pass in and not the one at class level. You should either refer to the form variable with this qualifier, or preferably rename it.
A common practice is to use underscore prefix for class level variables:
class Game
{
private Form1 _form;
public Game(Form1 form) {
_form = new Form1();
}
}
Use this in constructor Game Class :
public Game(Form1 form)
{
this.form = form;
}
You are creating a new form instead of assigning the passed in form to its local variable.
class Game {
private Form1 form;
public Game(Form1 form) {
*form = new Form1();*
}
public void RollDice() {
form.ShowMessage("blahblah");
}
You should change the code so the passed in form will be assigned to its local variable like this:
public Game(Form1 form) {
this.form = form;
}
Then it should work.
Don't let your Game class know about the Form that's calling it. That really limits the reusability of your code in the future, since now any Form that tries to use the Game class has to have a ShowMessage method to call.
Instead, just have your RollDice method return a string...
class Game
{
public void RollDice()
{
// do important 'roll dice' stuff...
return "blahblah";
}
}
And then have your Form handle the return value appropriately.
private void btnRoll_Click(object sender, EventArgs e)
{
string message = game.RollDice();
lblMessage.Text = message;
}
That completely gets around the need to pass the Form into your Game class, and avoids a lot of opportunities for getting a NullReferenceException.

Sending data between 2 windows forms of which one is singleton

I have following problem i have 2 windows forms and to send data between them i figured out that in Form2(which is called by Form1) constructor i will be passing reference to Form1 .
Like this public Form2(Form callingForm)
{
mainForm = callingForm as Form1;
InitializeComponent();
}
But I would like Form2 to be singleton and somehow I don't know how to achieve that along with passing form1's reference to form2. I reviewed documentation https://msdn.microsoft.com/en-us/library/ff650316.aspx and I have no clue how to edit this example to fit my needs. So I am able to make singleton constructor or make constructor that takes reference to form1, but not both.
If Form1 is your application's Main Form then you should use --> Appliction.MainForm. That way you don't need the parameter.
Edit: I was not trying to be obtuse and not answer your question. You can create a singleton with parameters using multiple constructors, however, I would try to avoid it.
private Singleton(param1,param2)
public static Singleton MyInstance(param1,param2)
I am not sure I am understand your question very well, but I think, you can implement Lazy.. (Lazy itself implements Singleton pattern). Maybe something like this:
class Form1
{
public Form2 Callee
{
get;
set;
}
public Form1()
{
Callee = Form2.Instance(this).Value;
}
}
class Form2
{
public static Lazy<Form2> Instance(Form1 caller)
{
return new Lazy<Form2>(() =>
{
return new Form2(caller);
});
}
public Form1 Caller
{
get;
private set;
}
Form2(Form1 caller)
{
Caller = caller;
}
}
Ok i seem to have solved this problem, here is the code:
private Form1 mainForm = null;
public Form2(Form callingForm)
{
mainForm = callingForm as Form1;
InitializeComponent();
}
public static Form2 Instance
{
get
{
if (instance == null)
{
instance = new Form2(Application.OpenForms[0] as Form1);
}
return instance;
}
}
#lrb thank you, basically i had problem in this line, cuz couldn't pass anything as parameter
instance = new Form2(Application.OpenForms[0] as Form1);
and Application.OpenForms[0] helped.

how to edit the primary form using a form that was created from the primary form in C#

I want to edit a primary form(Form1) using a form that is created from its code(Form2). The way I have done it is that, when the event is triggered, the new form appears, and everything works, but I want it so that when a button is pressed, the original form is edited. The code I have tried is this:
Form1 form1 = new Form1();
private void button1_Click(object sender, EventArgs e)
{
form1.startNewGame();
this.Hide();
}
By the way, I realise that this is creating a new instance of the form, I want to know how to edit the already existing instance of the form.
Without having the code of Form2 is hard to help you, but I will try. Instead of creating an instance of Form1, add a public property to form2
public Form1 PrimaryForm{get;set;} and when you showin form2 set that property to this
A solution would be to pass a reference of your Main Form to the child form when the child form is initialized. You can then set the value of the mainform through the reference. See below for an example:
public class ChildForm1 : Form
{
// Fields
private MainForm _mainForm;
private bool _value1;
private bool _value2;
// Default constructor
public ChildForm1()
{
}
// Overloaded constructor that accepts a container of values
public ChildForm1(ValuesContainer values, MainForm mainForm)
{
_mainForm = mainForm;
_value1 = values.Value1;
_value2 = values.Value2;
//Set a main form value
_mainForm.Value = "This value was changed by ChildForm1."
}
}
public class ChildForm2 : Form
{
// Field
private bool _value3;
// Default constructor
public ChildForm2()
{
}
// Overloaded constructor that accepts a container of values
public ChildForm2(ValuesContainer values)
{
_value3 = values.Value3;
}
}
public class MainForm : Form
{
public string Value { get; set; }
// Default constructor
public MainForm()
{
}
// Simulated - Event method called when button is clicked for child form 1
public void CallChildForm1()
{
ValuesContainer values = new ValuesContainer();
// Set the values from the main form
values.Value1 = true;
values.Value2 = true;
// Call the child form while passing in the container of values that we just populated.
ChildForm1 childForm = new ChildForm1(values);
childForm1.Show();
}
// Simulated - Event method called when button is clicked for child form 2
public void CallChildForm2()
{
ValuesContainer values = new ValuesContainer();
// Set the value from the main form
values.Value3 = true;
// Call the child form while passing in the container of values that we just populated.
ChildForm2 childForm = new ChildForm2(values);
childForm2.Show();
}
}
// Simple data object or container used to transfer information between complex objects such as forms and controls.
// These are also known as data classes or data transfer objects (DTOs)
public class ValuesContainer
{
public bool Value1 { get; set; }
public bool Value2 { get; set; }
public bool Value3 { get; set; }
}
This might not be the best practice but is the simplest way to do it. Here are the steps;
1) in Form1 add a public method to edit whatever you want
2) in Form2 add a reference to type Form1
3) instantiate Form2 and set InstanceOfForm2.ReferenceToForm1 = this;
4) in the event handler of Form2 use the reference to call your public method like
//inside some event handler
this.ReferenceToForm1.MyPublicMethodThatEditsTheDisplay();
One thing to remember is that Form1 is just an object like any other. The only thing preventing you from editing it anywhere you choose is the access level of it's properties (can't touch private fields, obviously) and the lack of reference. Everything beyond that is a matter of opinion and 'best practice' if you want to edit from anywhere, make the field public/provide a public method and pass/set a reference.

Accesing Richtextbox from a class

I'm trying to append text in my richtextbox which is called ConsoleText. It's not working very well. I'm using a property in my form to access the richtextbox in the Class.
It looks like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//Skipped the rest
public string ACText
{
set
{
ConsoleText.AppendText(value);
}
}
Now from my class's constructor.
public McDonalds(string email, string pass)
{
Form1 f = new Form1();
f.ACText = "test";
}
It's not showing any text in my richtextbox sadly. I know it works, because i can in the property use a messageBox and see that the value is passed into it.
Thanks in advance i really need help with this.
Calling Form1 f = new Form1(); does not give you a reference to an existing form, it creates a new one with blank/default values in the form's controls.
HOW to solve this greatly depends on your design. If you want to tie your class to that form implementation, our class needs either a reference to the form, a reference to the control, or the value of the control that you're interested in passed to it.
For example:
public McDonalds(string email, string pass, Form1 form)
{
form.ACText = "test";
}
A cleaner solution would be to RETURN a value from your McDonalds class and let the FORM set the control value appropriately rather than tying your class to that form class.
you can use Singleton:
Singletons make having single instances easy. They allow for single allocations and instances of data. We review the singleton types. We see one of the fastest implementations. And we review other possibilities.
public partial class Form1 : Form
{
public static Form1 instance = null;
public Form1()
{
instance = this; //add this class to singleton
InitializeComponent();
}
public void Show(string Message)
{
MyConsole.Text = Message;
}
another class:
Form1.instance.Show("blah blah");
Create Delegate in Form1 Class binded method ACText (string val), and Pass the Delegate to McDonalds Class. Fire the Delegate
namespace YourNameSpace
{
public delegate void RichTextBoxDelegate(string text);
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
public void ACText(string s)
{
ConsoleText.AppendText(s);
}
// In Some Method Call MCDonald's form
public void ShowMcDonalds()
{
RichTextBoxDelegate deleg = new RichTextBoxDelegate(ACText);
MCdonalds ob = new McDonalds(deleg);
ob.show();
}
}
}
Pass the deleg to McDonalds form
Just fire the Delagate
public McDonalds(RichTextBoxDelegate sp)
{
Form1 f = new Form1();
sp("This is Test");
}
deleg("Test value"); // form McDonald's Form

Categories

Resources