|
Page 1 of 1 |
|
Posted: Wed, 23rd Jul 2014 03:27 Post subject: C# winforms, passing an Integer |
|
 |
I have four forms; each has their own job.
First form is entering name etc..
Second form asks which grade 1/2/3
Third form asks which Arithmetic, Addition/Subtraction.. etc..
Four form delivers the questions, two text boxes delivering random numbers based on the chosen grade.
What I want is for when the user clicks Grade One button to do this, the code below will be in form 2 (grade selection buttons).
form4 questions = new form4();
public void gradeOne_Click(...)
{
int grade = 1;
questions.Grade = grade; // Grade is the property which returns private int grade in form4.
then call arithmetic form.
then hide this form.
}
What I'm asking is, is:
int grade = 1;
questions.Grade = grade;
Will this pass the Integer to form4 so I can use that Integer to determine which random numbers are generated?
If not, how would I pass an Integer that is initialized and assigned in form2 and pass it to form4.
I'm sorry for the length of this post.
I've been stuck for days trying to do this.
|
|
Back to top |
|
 |
|
Posted: Wed, 23rd Jul 2014 14:50 Post subject: |
|
 |
Hi, I just built a small test, maybe this will give you what you need?
First of all, I create a new Class. This class will keep all your data between the various forms in sync:
Code: |
public class SharedData: INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private void NotifyPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
private String username = "none";
public String Username
{
get { return username; }
set
{
username = value;
NotifyPropertyChanged("Username");
}
}
}
|
For now please ignore all the stuff with PropertyChanged and so on
For each variable that you want to access across your application just create a private variable (like here, with username) and a public property so that you can access it
Now let's come to the magic code inside your forms. Form1 (it only has one single textbox):
Code: |
public partial class Form1 : Form
{
Form form2;
SharedData sharedData = new SharedData();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
form2 = new Form2(sharedData); // here we pass to our form2 our sharedData
form2.Show();
textBox1.DataBindings.Add("Text", sharedData, "Username");
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
sharedData.Username = ((TextBox)sender).Text;
}
}
|
And here form2 (also has nothing but a textbox):
Code: |
partial class Form2 : Form
{
SharedData sharedData;
public Form2(SharedData _sharedData) // received the sharedData from form1
{
sharedData = _sharedData;
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
textBox1.DataBindings.Add("Text", sharedData, "Username");
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
sharedData.Username = ((TextBox)sender).Text;
}
}
|
Now if you change your textbox in form1 it will auto update the textbox in form2.
Of course you can define variables that do not have any data binding to a gui object and just store them in the sharedData
As you can see I also implemented data binding. If this makes it too complex for you, then just use the part were we create our own class (minus all the propertychanged mumbojumbo) and pass the instance created in the first form to the second form. But honetsly, databinding is good. You won't need to worry about updating your form if you change the value of your stuff anywhere and changes on the gui will update the data aswell
PS:
xxx_Load(object sender, EventArgs e)
and
xxx_TextChanged(object sender, EventArgs e)
are auto created events that are created by visual studio if you double click on the forms (for _Load) and double click on the textbox (for _TextChanged)
=> NFOrce GIF plugin <= - Ryzen 3800X, 16GB DDR4-3200, Sapphire 5700XT Pulse
Last edited by PumpAction on Wed, 23rd Jul 2014 15:15; edited 1 time in total
|
|
Back to top |
|
 |
|
Posted: Wed, 23rd Jul 2014 15:05 Post subject: |
|
 |
Mini solution sans databinding:
SharedData class
Code: |
internal static class SharedData
{
internal static string hello = "world";
}
|
Form1 (one button)
Code: |
public partial class Form1 : Form
{
Form2 form2 = new Form2();
public Form1()
{
InitializeComponent();
form2.Show();
}
private void button1_Click(object sender, EventArgs e)
{
SharedData.hello = "Fuck off";
form2.update();
}
}
|
Form2: (one textbox)
Code: |
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
update();
}
internal void update() //can be called from outside to update the gui of form2
{
textBox1.Text = SharedData.hello;
}
}
|
|
|
Back to top |
|
 |
|
Posted: Wed, 23rd Jul 2014 17:04 Post subject: |
|
 |
I appreciate all the hard work you've put into that pump; I think you may have misunderstood what I'm trying to achieve though mate.
I can pass data (strings).
I just need to associate a button click with a grade number integer; pass that integer to form4 from form2 and then run a equality check on it (if statement).
private void gradeOne_Click(...)
{
grade = 1;
F4.Grade = grade; //Pass initialized variable to form4 Grade Property which sets private int grade within form4..
call form3;
hide this form;
}
Form4 is the questions form; once this has been loaded; it runs equality check on private int grade and then calls the arithmetic class based on the variable being grade 1/2/3.
Does that perhaps make it a little clearer mate?
Thank you for your time though; I appreciate it a lot.
|
|
Back to top |
|
 |
|
Posted: Wed, 23rd Jul 2014 17:09 Post subject: |
|
 |
OK to answer your first question, yes, if your Properties modifier is set to public, why wouldn't this work?
I'd still advise creating a class that holds your data instead of sending data fragments around.
|
|
Back to top |
|
 |
|
Posted: Wed, 23rd Jul 2014 17:12 Post subject: |
|
 |
Yup, ti's set to public; however, once I test it; the grade integer doesn't pass.
I have an if statement in form4_load that has the if statement check on the newly set grade variable.
Apparently it doesn't pass though.
I wonder if it's because I haven't allocated the constructor; I've made the private int grade in form4 but haven't allocated the variable in the constructor.
|
|
Back to top |
|
 |
|
Posted: Wed, 23rd Jul 2014 17:17 Post subject: |
|
 |
And you are sure that you are not creating new instances of your forms?
|
|
Back to top |
|
 |
|
Posted: Wed, 23rd Jul 2014 17:19 Post subject: |
|
 |
All instances/references to form objects are created inside the class but at the top before the constructor.
|
|
Back to top |
|
 |
|
Posted: Wed, 23rd Jul 2014 19:00 Post subject: |
|
 |
Form 2:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace CAI_GUI
{
public partial class Form2 : Form
{
Form3 arithmeticSelect = new Form3();
Form4 F4 = new Form4();
private int grade;
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void button4_Click(object sender, EventArgs e)
{
Environment.Exit(0);
}
private void gradeOne_Click(object sender, EventArgs e)
{
grade = 1;
F4.Grade = grade;
arithmeticSelect.Show();
this.Hide();
}
}
}
Form 4:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace CAI_GUI
{
public partial class Form4 : Form
{
int repeat = 0;
private int grade;
Arithmetic A1 = new Arithmetic();
public Form4()
{
InitializeComponent();
}
private void Form4_Load(object sender, EventArgs e)
{
if (grade == 1)
{
num1.Text = A1.firstRandomNumber().ToString();
num2.Text = A1.secondRandomNumber().ToString();
}
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
}
private void textBox2_TextChanged(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
Environment.Exit(0);
}
private void submit_Click(object sender, EventArgs e)
{
if (grade == 1)
{
repeat++;
num1.Text = A1.firstRandomNumber().ToString();
num2.Text = A1.secondRandomNumber().ToString();
if (repeat == 10)
{
Form1 mainMenu = new Form1();
mainMenu.Show();
this.Hide();
}
}
}
public int Grade
{
get { return grade; }
set { grade = value; }
}
public void changeSymbolAddition()
{
symbol.Text = "+";
}
public void changeSymbolSubtraction()
{
symbol.Text = "-";
}
private void symbol_Click(object sender, EventArgs e)
{
}
}
}
|
|
Back to top |
|
 |
|
Posted: Wed, 23rd Jul 2014 19:32 Post subject: |
|
 |
Where's the code that actually shows the F4 form?
At a first glance, I would also check if the Load event on F4 fires when you think it does in the debugger.
In general though, I would listen to Mr. PumpAction - you would normally have some shared data to manipulate to do these things you want to do.
Or alternatively, you could have some sort of "manager" class, that controls which forms to show, retrieve data from them and use the data as parameters to execute specific methods on the appropriate forms directly.
|
|
Back to top |
|
 |
|
Posted: Thu, 24th Jul 2014 02:55 Post subject: |
|
 |
Thank you for the advice; a dedicated class to handle all data does seem logical.
|
|
Back to top |
|
 |
|
Posted: Tue, 29th Jul 2014 20:08 Post subject: |
|
 |
I wanted to add a new element to my design that I'm trying to figure out; complete with code:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Skip_Form_Passing_Data_Test
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int number = int.Parse(textBox1.Text);
Form2 F2 = new Form2(number);
F2.Show();
this.Hide();
}
private void Form1_Load(object sender, EventArgs e)
{
}
private void button2_Click(object sender, EventArgs e)
{
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Skip_Form_Passing_Data_Test
{
public partial class Form2 : Form
{
private int data;
public Form2(int _data)
{
data = _data;
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
Form3 F3 = new Form3(data);
F3.Show();
this.Hide();
}
private void Form2_Load(object sender, EventArgs e)
{
}
}
}
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
namespace Skip_Form_Passing_Data_Test
{
public partial class Form3 : Form
{
private int data;
public Form3(int _data)
{
data = _data;
InitializeComponent();
}
private void label1_Click(object sender, EventArgs e)
{
}
private void Form3_Load(object sender, EventArgs e)
{
label1.Text = data.ToString();
}
public int Data
{
get { return data; }
}
private void button1_Click(object sender, EventArgs e)
{
Environment.Exit(0);
}
}
}
These are my three forms; this is the only way I've been able to pass a value successfully between three forms.
Originally I wanted to be able to use just the Property accessors and call F3.Data = int.Parse(textbox1.text);
however, this would not work once I jumped from form 1, to form 2 and then to form 3.
Essentially it looked like this:
public form1()
{
//stuff
}
public button_click(...)
{
int number = int.Parse(textbox.text);
form2 F2 = new form2();
form3 F3 = new form3();
F3.Data = number;
F2.show();
this.hide();
}
public form2()
public void button_Click(...)
{
form3 F3 = new form3();
F3.Show();
this.hide();
}
Form2 would just have a button that said proceed; this was just to text if the number within the text box would just assign to F3.Data and still be able to go through form2 and then click proceed to form 3 and show the entered value from form 1.
It only worked if I had two forms or passed via constructor.
F3.Data wouldn't retain the value once it hit F2.show();
then his proceed on F2 and it was blank on F3;
Any suggestions as to why it would only pass the value if I did it with a constructor and passed the value through form2 as appose to just setting F3.Data in form1?
|
|
Back to top |
|
 |
[mrt]
[Admin] Code Monkey
Posts: 1342
|
Posted: Sat, 2nd Aug 2014 20:47 Post subject: |
|
 |
Hey there Rayne,
Its simple why. I assume the two c&p's above are for Form1 and then for Form2 classes. In Form1's button_click() you create an instance of F3 and assign it the F3.Data = number. But you then discard that instance and create a new instance of Form3 in Form2. The variables do have the same name, at both places, but are local variables, which means they only exist in the function button_click() and then disappear. The result is that the forms do look the same, but they are different - like a couple of drawers, you put something in the top one, close it and when you go look for whatever you have put in there you open up the bottom one. They look the same yet they contain different things. If you want persistence you need to create the forms at startup and only manage their state with a series of Show() and Hide()'s.
In either case its not a very good way of passing data around. You should have a central place where all data should reside in and be manipulated at, the forms should only display and reflect the data contained therein. Essentially what Pumpy showed you.
The reason why passing via constructor worked was because the data got passed around like at an olympic relay to whichever instance of the form that was created, even if you had created three more the data would have stayed the same.
teey
|
|
Back to top |
|
 |
|
Posted: Sun, 3rd Aug 2014 23:38 Post subject: |
|
 |
So, is using a Constructor deemed as good programming practice?
When you say create the forms at startup; can you please clarify?
Perhaps a website link or code demonstration?
I'm a visual/hands on learner.
Thanks.
|
|
Back to top |
|
 |
|
Posted: Mon, 4th Aug 2014 08:46 Post subject: |
|
 |
Rayne01 wrote: | So, is using a Constructor deemed as good programming practice?
When you say create the forms at startup; can you please clarify?
Perhaps a website link or code demonstration?
I'm a visual/hands on learner.
Thanks. |
Pumpy already posted you an example code in his very first replies, and it's pretty much what you need. The general idea is this:
First, you don't use the int as data directly. Create a class instead, and use its fields/properties to store data. That way, each form will only need to hold a reference to the instance of that class, which you can pass in to the constructor on startup (basically replace "int data" in your code with "Data data", where Data is a class you created).
In your main Form, create instances of all the forms and data you want to use and pass that data to the forms that need it as a constructor parameter, but don't show the forms until you need to.
The main form will also need to be aware of which forms to show and when. The first one you can just show directly, obviously, but for the others you could subscribe to the events of those forms (respond to when the form gets hidden/closed for example), or create your own events.
For simplicity, you could just add buttons on the main form that will Show()/Hide() each form to see how it works, and then keep going from there to automate the process.
The other part would be making the forms aware of the data changes, but Pumpy showed you how to handle that as well.
|
|
Back to top |
|
 |
|
Posted: Mon, 4th Aug 2014 09:25 Post subject: |
|
 |
When I have time I will create you a dummy project. Later today I should have some mins for this 
|
|
Back to top |
|
 |
|
Posted: Mon, 4th Aug 2014 12:49 Post subject: |
|
 |
|
|
Back to top |
|
 |
|
Posted: Tue, 5th Aug 2014 04:16 Post subject: |
|
 |
Thank you; I've downloaded and I'll have a look.
I appreciate your time and patience.
|
|
Back to top |
|
 |
|
Posted: Tue, 5th Aug 2014 11:16 Post subject: |
|
 |
No problem, I hope this answers some questions 
|
|
Back to top |
|
 |
Page 1 of 1 |
All times are GMT + 1 Hour |
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB 2.0.8 © 2001, 2002 phpBB Group
|
|
 |
|