I am learning C# and have run into an interesting issue to me. I have a class variable defined as public and I instantiate a new instance of my form in my class and access the value of the public variable it is always null.
To further explain my issue - this syntax prints the appropriate value
System.Diagnostics.Debug.WriteLine(tboxvalue.ToString());
However, this syntax is always outputting a 0
System.Diagnostics.Debug.WriteLine(f1.tboxvalue.ToString());
How do I need to alter my syntax so that the correct value is passed to the class Functions?
public partial class Form1 : Form
{
public double tboxvalue;
private string exportdata;
public Form1()
{
InitializeComponent();
}
private void btnClicker_Click(object sender, EventArgs e)
{
Functions.EE();
}
private void txtData_CheckedChanged(object sender, EventArgs e)
{
bool #checked = ((CheckBox)sender).Checked;
if (#checked.ToString() == "True")
{
exportdata = "Yes";
tboxvalue = Convert.ToDouble(this.txtData.Text);
System.Diagnostics.Debug.WriteLine(tboxvalue.ToString());
}
else
exportdata = "No";
}
}
class Functions
{
public static void EE()
{
Form1 f1 = new Form1();
System.Diagnostics.Debug.WriteLine(f1.tboxvalue.ToString());
}
}
To access properties of the form, you need to change two Things. First you have to pass the form to the 'EE' method, then you can access the form's properties. Second, don't create a new form in 'EE' method.
public partial class Form1 : Form
{
public double tboxvalue;
private string exportdata;
public Form1()
{
InitializeComponent();
}
private void btnClicker_Click(object sender, EventArgs e)
{
Functions.EE(this);
}
private void txtData_CheckedChanged(object sender, EventArgs e)
{
bool #checked = ((CheckBox)sender).Checked;
if (#checked.ToString() == "True")
{
exportdata = "Yes";
tboxvalue = Convert.ToDouble(this.txtData.Text);
System.Diagnostics.Debug.WriteLine(tboxvalue.ToString());
}
else
exportdata = "No";
}
}
class Functions
{
public static void EE(Form1 f1)
{
System.Diagnostics.Debug.WriteLine(f1.tboxvalue.ToString());
}
}
If i understood your question i guess you are recreated Form1 with own textbox or labels when you click btnClicker button. You can reassign your form objects where you created it.
You might add static Form1 object and Setter routine to Functions class:
private static Form1 _form;
public static void SetForm(Form1 form)
{
_form = form;
}
and pass the form to the class in Form_Load event-click on the form twice:
private void Form1_Load(object sender, EventArgs e)
{
Functions.SetForm(this);
}
Then you can play with the form in Functions class using the object _form
good luck!
Related
{
public partial class form1 : Form
{
public form1()
{
InitializeComponent();
}
public Button ButtonName { get { return } }
public static int initFaggleCount;
private void button1_Click(object sender, EventArgs e)
{
int faggleCount = initFaggleCount++;
string finalCalc = faggleCount.ToString();
label1.Text = finalCalc;
/*
Console.WriteLine(faggleCount);
Console.ReadLine();*/
}
private void button2_Click(object sender, EventArgs e)
{
/*TextWriter tw = new StreamWriter("SavedFaggleCount.txt");
tw.WriteLine();
tw.Close();*/
Console.WriteLine(faggleCount);
Console.ReadLine();
}
}
}
I would like the integer faggleCount to be accessible from button2 so that I can successfully Console.WriteLine(fagleCount); from button2. I'm a noob and any help is appreciated. Thanks!
instead of declaring local variable inside method body you can declare instance variable so that all members of class can access it.
public partial class form1 : Form
{
int faggleCount; //declare instance variable.
public form1()
{
InitializeComponent();
}
public Button ButtonName { get { return } }
public static int initFaggleCount;
private void button1_Click(object sender, EventArgs e)
{
faggleCount = initFaggleCount++; //use instance variable
string finalCalc = faggleCount.ToString();
label1.Text = finalCalc;
/*
Console.WriteLine(faggleCount);
Console.ReadLine();*/
}
private void button2_Click(object sender, EventArgs e)
{
/*TextWriter tw = new StreamWriter("SavedFaggleCount.txt");
tw.WriteLine();
tw.Close();*/
Console.WriteLine(faggleCount); //use instance variable
Console.ReadLine();
}
}
In your code, faggleCount is local to the method i.e. only code in the method can access it. What you need to do is to move the variable to the class-level. like this:
public class form1 : Form {
int faggleCount;
//your other code here
}
As you can see, the variable is now in the class, not in the method. This way all the methods in the class can access it, and even a inner class can access it too!
This problem is very common among beginners. Understanding the scope of the variable is pretty hard. In short, A variable in a class can be accessed in the class, a variable in a method can be accessed in the method.
In a college project we're developing an average CRUD application, we're being told to create a Create form and a Update form that are identical save that the Update one loads with data of an object that selected on a list beforehand, besides both forms are exactly the same.
Wouldn't it be more efficient to just use the same Create form?
I was thinking in something like adding a boolean to the form constructor, true for create and false for update, but I don't know if this is good practice.
Something like this:
public partial class frmLocal
{
private bool isCreate;
private int objId;
public frmLocal(boolean _isCreate, int _id = 0)
{
InitializeComponent();
isCreate = _isCreate;
objId = _id;
}
private void frmLocal_Load(object sender, EventArgs e)
{
if(isCreate)
{
try
{
//Shows blank create form
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "Error.");
}
}
else
{
//Loads an object's data with some stored procedure
}
}
}
I think it is a better practice to create a public property and set the value before create the instance of the new form.
So in your form you will have:
public partial class Form2 : Form
{
public bool IsCreate { get; set; }
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
if (IsCreate)
{
//load specific controls/data for creating
}
else
{
//load specific controls/data for updating
}
}
}
And supposing you have a Form1 to open the Form2, you will use:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
var formCreateUpdate = new Form2 {IsCreate = true};
formCreateUpdate.Show();
}
}
I am trying to finds a way to have access to methods and variables of a form and a class from each other using instance. Here is my code:
My form code is:
public partial class Form1 : Form
{
int var1 = 0;
public Form1()
{
InitializeComponent();
Glob glob = new Glob(this);
}
private void button1_Click(object sender, EventArgs e)
{
}
}
and my class code is:
public class Glob
{
private Form1 _form;
public Glob(Form1 parent)
{
_form = parent;
}
public int Func1()
{
return 10;
_form.var1 = 10;
}
}
I can call form methods from my class, but I can not call class methods from button1_Click event! What is wrong with my code please?
This will never set the property:
public int Func1()
{
return 10;
_form.var1 = 10;
}
The function returns before the property is set. You should be getting an unreachable code warning.
Also, your var1 variable is private. You need to make it public (capitalize it too). This is so it can be accessed outside of where its declared:
public int Var1 { get; set; }
In addition.. you want your Glob instance to be form level:
private Glob _glob;
public Form1()
{
InitializeComponent();
_glob = new Glob(this);
}
Then you can call it in the click event:
private void button1_Click(object sender, EventArgs e)
{
_glob.Func1();
}
That's because your scope for glob is local to your constructor. Declare it as a module level variable and it will work just fine.
public partial class Form1 : Form
{
int var1 = 0;
Glob glob;
public Form1()
{
InitializeComponent();
glob = new Glob(this);
}
private void button1_Click(object sender, EventArgs e)
{
glob.Func1();
}
}
[Edit]
Simon Whitehead's answer gives more detail of the other problems you have, but mine addresses your specific question of "Why can't I call glob from my button click?"
I have two forms, Form1 and Form2. Form1 has a variable int x. When the program is executed, Form1 is hidden and Form2 is shown; however i need to call the variable from the existing Form1.
I know the method to call the variable by calling a new instance of Form1.
Form1 r = new Form1();
r.x = 20;
But I want to know how to do it for an already opened Form1.
Take several cases, like if there are multiple variables that are called from Form1, by several forms (Form2, Form3, Form4 etc...). Any variable can be called from Form1 by the forms. Also, forms can call variables from other forms (Like if Form1 and Form2 is open, then Form3 can call variables from Form1 AND Form2)
I know its a huge list, but would really appreciate if anyone can find a good way to implement it.
You will have to have a reference to the "already opened" form1 instance, so that you can reference the value of x on that form.
So, lets say that Form2 instantiates the hidden form1. You will have to have a reference in form2 to the form1, to reference the variable.
OK, Lets say this is the code for form2
public partial class Form2 : Form
{
private Form1 f;
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
f = new Form1
{
Visible = false
};
int x = f.X;
}
}
and then code for form1
public partial class Form1 : Form
{
public int X { get; set; }
public Form1()
{
InitializeComponent();
X = 20;
}
}
and you need to ensure that the form luanched from the program class is
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form2());
}
}
You can do it in following ways,
in my case form1 is form4 and form2 is form5. please consider, :)
//code on form4:
// this is by passing the reference of the form to other form
public partial class Form4 : Form
{
public int a { get; set; }
public int b { get; set; }
public Form4()
{
InitializeComponent();
}
private void Form4_Load(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
a = 5;
b = 6;
Form5 frm5 = new Form5();
frm5.frm4 = this;
this.Close();
frm5.Show();
}
}
// code on form5
public Form4 frm4 { get; set; }
private void Form5_Load(object sender, EventArgs e)
{
int x = frm4.a;
int y = frm4.b;
}
Also you can have a class file in which the instance of the form1 will be static, so that you can use that instance on form2 to refer to the form1's properties.
Let me know, if it does not solve your problem.
I hope it will help you. :)
Create a public property on the form itself. Have the get accessor return the form value. You can call it like this. Form1.MyProperty;
public string MyPrperty {
get {
return Form1.txtExample.text;
}
}
EDIT:
You can return a dictionary of all of those values if you have that many to return at a time. I would seriously consider rethinking your form if you have 20-40 values being filled. That sounds like a poor user experience to me.
i think there is a reason that you wouldn't try System.Properties.Settings.Default
accessible from Project Menu --> Properties in visual studio...
Thanks...
My guess is that you are looking for System.Windows.Forms.Application.OpenForms property which holds all the open forms in an array.
What you need to do is to check the type of each form and if it is equivalent to Form1 access the variable's value. Also, to access the variable outside the form you need to set its access modifier to either Public or make a corresponding property for it.
EDIT
Here is a sample code: (untested)
public partial class Form1 : Form
{
public int X;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
X = 100;
Form2 frm = new Form2();
frm.Show();
this.Hide();
}
}
public partial class Form2 : Form
{
int local_X = 0;
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
foreach(Form f in System.Windows.Forms.Application.OpenForms)
{
if(typeof(f) == typeof(Form1))
{
local_X = f.X; // access value here and set in local variable
}
}
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Value of X is : " + local_X); // Show alert for value of variable on button click
}
}
EDIT
Or you can use constructor overloading to accomplish this task:
public partial class Form1 : Form
{
public int X;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
X = 100;
Form2 frm = new Form2(x); // pass variable to form2, if multiple values pass int array
frm.Show();
this.Hide();
}
}
public partial class Form2 : Form
{
int local_X = 0;
public Form2()
{
InitializeComponent();
}
// Overloading of constructor
public Form2(int X) // if multiple values pass int array
{
InitializeComponent();
local_X = x; // capture value from constructor in class variable.
}
private void Form2_Load(object sender, EventArgs e)
{
// no need to iterate here for now due to overloading value get passed during initialization.
}
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show("Value of X is : " + local_X); // display value if alert box.
}
}
Let's look at the situation.You have multiple forms in your application and you want to do access several variables these forms.
My guess is,
public static class GlobalVariables
{
public static object MyVariable1 { get; set; }
public static object MyVariable2 { get; set; }
}
So you can access variables everywhere in your project.
It doesn't matter whether which form is opened or closed. Your ultimate goal is to access a member from Form1 in Form2 isn't it? If that is the case when you create an instance of your Form2, do it like this
Form1 objForm1 = new Form1();
Form2 obj = new Form2(objForm1);
so that in form 2 class looks like this
class Form2: Form
{
private Form1 form1Object;
public Form2(Form1 obj)
{
form1Object = obj;
}
private void SomeMethodInForm2()
{
//Here you can access the variable in form1 like
form1Object.PropertyNameYouWantToAccess;
}
}
The form 1 class can look like this
class Form1: Form
{
public int PropertyNameYouWantToAccess{get;}
}
In my app in several time i have to call a window(class). the work of this window is to show the meaning of a word.when i again call that window a new window shows but the previous one also shows.
I have two form named form1,form2.
Form1 is like that:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string a = textBox1.Text;
Form2 s = new Form2(a);// it will be called as many time as i click
s.Show();
}
}
Form2 is like that:
public partial class Form2 : Form
{
public Form2(string s)
{
InitializeComponent();
label1.Text = s;
}
}
what i want is that inside form1 if i call form2 it shows but if i call form2 again the previous form2 window will be closed automatically and new form2 window will be shown instead of previous one.
How can i do that????
Here's an example of storing the Form2 reference at class level, as mentioned by the others already:
public partial class Form1 : Form
{
private Form2 f2 = null;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
if (f2 != null && !f2.IsDisposed)
{
f2.Dispose();
}
string a = textBox1.Text;
f2 = new Form2(a);
f2.Show();
}
}
I think you should consider using singleton pattern.
You can implement it like this:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string a = textBox1.Text;
Form2.ShowMeaning(a);// it will be called as many time as you click
}
}
and Form2
public partial class Form2 : Form
{
private static readonly Form2 _formInstance = new Form2();
private Form2()
{
InitializeComponent();
}
private void LoadMeaning(string s)
{
label1.Text = s;
}
//Override method to prevent disposing the form when closing.
protected override void OnClosing(CancelEventArgs e)
{
e.Cancel = true;
this.Hide();
}
public static void ShowMeaning(string s)
{
_formInstance.LoadMeaning(s);
_formInstance.Show();
}
}
Hope it helps.