Can't use variable from public Form2 in private void? - c#

namespace Bus
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
string selectedItem=listBox1.SelectedItem.ToString();
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
groupBox1.Text=selectedItem;
}
}
}
When I run this, I get an error for selectedItem in private void saying that selectedItem does not exist in the current context.
Why is that? If I declare the string in public Form2(), shouldn't others be able to use it since it's public?

selectedItem is a local string for your Form2's constructor only. You need to either create it as a field or property for all components of your Form2 class to be able to access it.

define selectedItem as property or field:
namespace Bus
{
public partial class Form2 : Form
{
public string selectedItem {get; private set}
//private string selectedItem;
public Form2()
{
InitializeComponent();
selectedItem=listBox1.SelectedItem.ToString();
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
groupBox1.Text=selectedItem;
}
}
}

there are a number of things you need to consider here
firstly any variable created inside a method can only be used inside that method
because of this you need to upgrade it from a local variable to a class variable
secondly how are are going to upgrade it it can be done in several ways
Field : this is generally used to things that are only needed inside the class not outside (though they can be declared public this is not best practice)
eg
public partial class Form2 : Form
{
private string selectedItem;
Property : Properties are used when fields need to be used outside the class or when you need addition control over what happens when data is got or set
eg
public partial class Form2 : Form
{
public string SelectedItem{get;set;}
Static : this is when you need to access the variable from every instance of a class not just the one its set in, static can be either a field or property
eg
public partial class Form2 : Form
{
public static string SelectedItem{get;set;}
which you need is dependent on what you need to accomplish
also just because a class is public doesn't mean everything on it is public,
you might have things on it that are only useful inside the class (private)
only in the class or its descendent (protected)
only inside the project (internal)
or accessible to everything (public)
so you must set the access on each method or property separately (if you don't it will default to internal), properties allow you to set this for both the get and the set separately so you can have a property that anything can read from but only the class itself can change

Well, selectedItem is a local variable and can be used locally only, within the constructor scope in your case. Convert it into property:
namespace Bus
{
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
public String SelectedItem {
get {
if (null == listBox1.SelectedItem)
return "";
return listBox1.SelectedItem.ToString()
}
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
groupBox1.Text = SelectedItem;
}
}
}

You need to make it a class level field
namespace Bus
{
public partial class Form2 : Form
{
private string selectedItem;
public Form2()
{
InitializeComponent();
selectedItem=listBox1.SelectedItem.ToString();
}
private void listBox1_SelectedIndexChanged(object sender, EventArgs e)
{
groupBox1.Text=selectedItem;
}
}
}

Related

C#: Referencing an instance of a class that was made in another class

I need some help with C#.
Let's say I have 3 classes. MainMenu, Form1 and Data.
I have created an instance of Data (referenced as StoreData) in MainMenu.
public partial class MainMenu : Form
{
public Data StoreData = new Data();
}
I want to be able to access this instance of StoreData in Form1. How do I reference it or import it?
You can either
Make StoreData static 🤮 in a static class MyAWesomeStatic and call MyAWesomeStatic.StoreData or even in MainMenu class iteself.
Pass a reference of StoreData to Form1 either via the constructor or a property when you create it.
or pass a reference of MainMenu to form1 and call mainMenu.StoreData when needed.
However, another option might be to use Dependency Injection (DI) and Loosely Couple all this. Have a Singleton instance and pass the in-memory Data Store as some sort of Service (which is what the cool kids might do).
Update
Sorry, still at the beginning stages of learning C#. What does it mean
to make a class static?
Given your current level of knowledge and all-things-being-equal, i think the easiest approach might be just pass in a reference
public class Form1
{
public Data StoreData { get; set; }
}
...
var form = new Form1();
form.StoreData = StoreData;
form.Show();
If you want to reference one class within another class (and don't want to make anything static), composition is one way to go.
You want to reference field of MainForm in Form1, so you want to reference MainForm itself. Thus, you need to create field in Form1 of MainForm type:
public class Form1 : Form
{
...
public MainForm mf { get; set; }
...
}
Now, you can access StordeData with mf.StordeData within Form1.
You could make StoreData static in a static class, something like this:
public static class Form1
{
public static Data StoreData { get; set; }
}
Suppose your StoreData class have one property
public class StoreData
{
public int MyProperty { get; set; }
}
Add static property to your mainform.cs and assign value to MyProperty = 1
public partial class MainMenu : Form
{
public static StoreData Data { get; set; } //static property
private void MainMenu_Load(object sender, EventArgs e)
{
Data = new StoreData { MyProperty = 1 };
}
}
And access your StoreData property inside Form1.cs like
public partial class Form1 : Form
{
private void Form1_Load(object sender, EventArgs e)
{
var id = MainMenu.Data.MyProperty;
}
}
Try once may it help you
Result:

How to access chart property of Form2 from Form1 by clicking button action of Form1 in C# [duplicate]

I am trying to understand whats the difference between a static and public properties. But when I tried to access my public property 'Test' in other form it says 'null'.
Heres Form1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private string _test;
public string Test
{
get { return _test; }
set { _test = value; }
}
private void Form1_Load(object sender, EventArgs e)
{
_test = "This is a test";
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2.Show();
}
}
Here's Form2:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
Form1 frm1 = new Form1();
label1.Text = frm1.Test;
}
}
To check the value of 'Test' in Form1, I put a breakpoint to this line:
label1.Text = frm1.Test;
But the value is 'null'.
Please help me how can I access public properties to other forms.
And BTW I tried to make this public property be a 'public static'. I can access this using this:
Form1.Test
But I noticed that I can change 'Test' value from Form2 which I don't want to happen. That's why I am trying to use public property but with no luck. Can somebody clarify me these things. Thanks for all your help guys!
EDIT: (For follow up question)
Sir John Koerner's answer is the best answer for my question. But I have a follow up question, I tried to make these 'test' properties to be a 'static', and I noticed that even if I make this property a static or public property, it still can be edit in Form2. To make myself clear here's a sample:
public partial class Form2 : Form
{
private Form1 f1;
public Form2(Form1 ParentForm)
{
InitializeComponent();
f1 = ParentForm;
}
private void Form2_Load(object sender, EventArgs e)
{
label1.Text = f1.Test;
}
private void button1_Click(object sender, EventArgs e)
{
f1.Test = "This test has been changed!";
this.Close();
}
}
After Form2 closed, I tried to break again in Form1_Load to check value of 'Test', and it was changed! How can I make a public property in Form1 to readOnly in Form2 and cannot be editted? Please clarify to me. Thanks a lot guys!
Your property is an instance variable, so the value can be different across different instances of Form1.
If you are trying to access instance variables from a parent form, the easiest way to do that is to pass Form1 in to the constructor of Form2.
public partial class Form2 : Form
{
private Form1 f1;
public Form2(Form1 ParentForm)
{
InitializeComponent();
f1 = ParentForm;
}
private void Form2_Load(object sender, EventArgs e)
{
label1.Text = f1.Test;
}
}
Then when you create a new Form2 from Form1, you can do this:
Form2 frm2 = new Form2(this);
If you want your property to be read only, you can simply not specify a setter:
public string Test
{
get { return _test; }
}
Use of this method 'static'
At first Control label property Modifiers=Public
in Program code below
public static Form1 frm1 = new Form1();
public static Form2 frm2 = new Form2();
in Form1 code below
Program.frm2.show();
in Form2 code below
label1.Text=Program.frm1.text;
The frm1 not your main form object. It is newly created object where property Test initializes when it loads (in Form1_Load event handler).
The first instance of Form1 shows an instance of Form2, and then Form2 creates another instance of Form1. This could work, but you set _test in the Form.Load event, which:
Occurs before a form is displayed for the first time.
You do not show the instance of Form1 you're trying to read Test from, so its Load event will not occur and Test remains null.
You could add a constructor overload or property to pass the Form1 reference as #JohnKoerner mentions, but I would prefer to only pass the required variable, perhaps even encapsulated in an event, to reduce coupling. Form2 usually doesn't need to know all about Form1.
public
The type or member can be accessed by any other code in the same assembly or another assembly that references it.
static
The static modifier on a class means that the class cannot be instantiated, and that all of its members are static. A static member has one version regardless of how many instances of its enclosing type are created.
A static class is basically the same as a non-static class, but there is one difference: a static class cannot be externally instantiated. In other words, you cannot use the new keyword to create a variable of the class type. Because there is no instance variable, you access the members of a static class by using the class name itself.
However, there is a such thing as a static constructor. Any class can have one of these, including static classes. They cannot be called directly & cannot have parameters (other than any type parameters on the class itself). A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced. Looks like this:
static class Foo()
{
static Foo()
{
Bar = "fubar";
}
public static string Bar { get; set; }
}
Static classes are often used as services, you can use them like so:
MyStaticClass.ServiceMethod(...);

How do I get my class variables properties into Winform controls?

Currently I have multiple classes, one of which is called the 'Variable class' where I
{get;set;}
my values obtained from other classes. Accessing these values in voids is simply:
Private void (Variables vb)
{
}
However in the 'Load' part of Winforms,
private void Form1_Load(object sender, EventArgs e)
{
}
From the Variables Class:
public class Variables
{
public int Node { get; set; }
}
The object sender, EventArgs e part is occupying the space where I place the arguments. Is there any way that I could obtain Node from the class Variableson the winform?
Your method Form1_Load is an event handler (because it usually gets called as a result of some event occurring). The "Load" event is defined by WinForms, so you cannot change the fact that the arguments are object sender and EventArgs e.
WinForms creates one instance of your Form1 class before it displays your form. Whenever an event happens on your form, the event handler on that same object is called.
So, you can store values in fields and properties of your Form1 class:
public class Form1 : Form
{
Variables _myVariables;
public Form1()
{
InitializeComponent();
_myVariables = new Variables() { Node = 10 }
}
private void Form1_Load(object sender, EventArgs e)
{
MessageBox.Show("The current value of _myVariables.Node is: " + _myVariables.Node);
}
}
If your Variables object is created outside your form, then you can pass it into your Form1 constructor:
public class Form1 : Form
{
Variables _myVariables;
public Form1(Variables variables)
{
InitializeComponent();
_myVariables = variables;
}
// ...
}
// Then, somewhere else:
var variables = new Variables() { Node = 10 };
var myForm = new Form1(variables);
myForm.Show();
// or: Application.Run(myForm);
I'm not 100% sure if this is what you are looking for, but I think I can help.
namespace Example
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//class which can be used anywhere in the namespace
public class exampleClass
{
public const string SETSTATE = "0";
public const string GETSTATE = "1";
public const string SETVALUE = "2";
public const string GETVALUE = "3";
public const string SENDFILE = "4";
public const string STATE_RP = "129";
public const string VALUE_RP = "131";
public const string STATUS_RP = "128";
}
}
}
you can use exampleClass, and any of its enclosed members, anywhere within Form1 here. You do not need to pass it anywhere within the form to use it. You could add a function later that uses it directly like:
void exampleF()
{
//note that when you are accessing properties of UI elements from
//a non-UI thread, you must use a background worker or delegate
//to ensure you are doing so in a threadsafe way. thats a different problem though.
this.txtYourTextBox.txt = exampleClass.GETSTATE;
}
Maybe your attempt is it actually to use MVP-Pattern in WinForms. Very good idea.
Then you can use DataBinding to Bind your Forms-Controls to your "Variables classes" properties. Your variable class takes the presenter role, your form is the view, and your model(s) are the sources of your variable classes data.
Unfortunately, the pattern uses some advanced mechanisms you have to deal with.
For more information, you might take a first look here:
Databinding in MVP winforms

C# winform: Accessing public properties from other forms & difference between static and public properties

I am trying to understand whats the difference between a static and public properties. But when I tried to access my public property 'Test' in other form it says 'null'.
Heres Form1:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private string _test;
public string Test
{
get { return _test; }
set { _test = value; }
}
private void Form1_Load(object sender, EventArgs e)
{
_test = "This is a test";
}
private void button1_Click(object sender, EventArgs e)
{
Form2 frm2 = new Form2();
frm2.Show();
}
}
Here's Form2:
public partial class Form2 : Form
{
public Form2()
{
InitializeComponent();
}
private void Form2_Load(object sender, EventArgs e)
{
Form1 frm1 = new Form1();
label1.Text = frm1.Test;
}
}
To check the value of 'Test' in Form1, I put a breakpoint to this line:
label1.Text = frm1.Test;
But the value is 'null'.
Please help me how can I access public properties to other forms.
And BTW I tried to make this public property be a 'public static'. I can access this using this:
Form1.Test
But I noticed that I can change 'Test' value from Form2 which I don't want to happen. That's why I am trying to use public property but with no luck. Can somebody clarify me these things. Thanks for all your help guys!
EDIT: (For follow up question)
Sir John Koerner's answer is the best answer for my question. But I have a follow up question, I tried to make these 'test' properties to be a 'static', and I noticed that even if I make this property a static or public property, it still can be edit in Form2. To make myself clear here's a sample:
public partial class Form2 : Form
{
private Form1 f1;
public Form2(Form1 ParentForm)
{
InitializeComponent();
f1 = ParentForm;
}
private void Form2_Load(object sender, EventArgs e)
{
label1.Text = f1.Test;
}
private void button1_Click(object sender, EventArgs e)
{
f1.Test = "This test has been changed!";
this.Close();
}
}
After Form2 closed, I tried to break again in Form1_Load to check value of 'Test', and it was changed! How can I make a public property in Form1 to readOnly in Form2 and cannot be editted? Please clarify to me. Thanks a lot guys!
Your property is an instance variable, so the value can be different across different instances of Form1.
If you are trying to access instance variables from a parent form, the easiest way to do that is to pass Form1 in to the constructor of Form2.
public partial class Form2 : Form
{
private Form1 f1;
public Form2(Form1 ParentForm)
{
InitializeComponent();
f1 = ParentForm;
}
private void Form2_Load(object sender, EventArgs e)
{
label1.Text = f1.Test;
}
}
Then when you create a new Form2 from Form1, you can do this:
Form2 frm2 = new Form2(this);
If you want your property to be read only, you can simply not specify a setter:
public string Test
{
get { return _test; }
}
Use of this method 'static'
At first Control label property Modifiers=Public
in Program code below
public static Form1 frm1 = new Form1();
public static Form2 frm2 = new Form2();
in Form1 code below
Program.frm2.show();
in Form2 code below
label1.Text=Program.frm1.text;
The frm1 not your main form object. It is newly created object where property Test initializes when it loads (in Form1_Load event handler).
The first instance of Form1 shows an instance of Form2, and then Form2 creates another instance of Form1. This could work, but you set _test in the Form.Load event, which:
Occurs before a form is displayed for the first time.
You do not show the instance of Form1 you're trying to read Test from, so its Load event will not occur and Test remains null.
You could add a constructor overload or property to pass the Form1 reference as #JohnKoerner mentions, but I would prefer to only pass the required variable, perhaps even encapsulated in an event, to reduce coupling. Form2 usually doesn't need to know all about Form1.
public
The type or member can be accessed by any other code in the same assembly or another assembly that references it.
static
The static modifier on a class means that the class cannot be instantiated, and that all of its members are static. A static member has one version regardless of how many instances of its enclosing type are created.
A static class is basically the same as a non-static class, but there is one difference: a static class cannot be externally instantiated. In other words, you cannot use the new keyword to create a variable of the class type. Because there is no instance variable, you access the members of a static class by using the class name itself.
However, there is a such thing as a static constructor. Any class can have one of these, including static classes. They cannot be called directly & cannot have parameters (other than any type parameters on the class itself). A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced. Looks like this:
static class Foo()
{
static Foo()
{
Bar = "fubar";
}
public static string Bar { get; set; }
}
Static classes are often used as services, you can use them like so:
MyStaticClass.ServiceMethod(...);

Sending string from class to Form1

Although there are some similar questions I’m having difficulties finding an answer on how to receive data in my form from a class.
I have been trying to read about instantiation and its actually one of the few things that does make sense to me :) but if I were to instantiate my form, would I not have two form objects?
To simplify things, lets say I have a some data in Class1 and I would like to pass a string into a label on Form1. Is it legal to instantiate another form1? When trying to do so it looks like I can then access label1.Text but the label isn’t updating. The only thing I can think of is that the form needs to be redrawn or there is some threading issue that I’m unaware of.
Any insight you could provide would be greatly appreciated.
EDIT: Added some code to help
class Class1
{
public int number { get; set; }
public void Counter()
{
for (int i = 0; i < 10; i++)
{
number = i;
System.Threading.Thread.Sleep(5000);
}
}
}
and the form:
Class1 myClass = new Class1();
public Form1()
{
InitializeComponent();
label1.Text = myClass.number.ToString();
}
NO,
I think your form needs to access a reference to Class1 to use the data available in that, and not the other way around.
VERY seldomly a data class should instanciate a display form to display what it has to offer.
If the class is a data access layer of singleton, the form should reference that class, and not the other way around.
Based on the comments in your original post, here are a few ways to do it:
(this code is based on a Winform app in VS2010, there is 1 form, with a Label named "ValueLabel", a textbox named "NewValueTextBox", and a button.
Also, there is a class "MyClass" that represents the class with the changes that you want to publish.
Here is the code for the class. Note that I implement INotifyPropertyChanged and I have an event. You don't have to implement INotifyPropertyChanged, and I have an event that I raise whenever the property changes.
You should be able to run the form, type something into the textbox, click the button, and see the value of the label change.
public class MyClass: System.ComponentModel.INotifyPropertyChanged
{
public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;
public string AValue
{
get
{
return this._AValue;
}
set
{
if (value != this._AValue)
{
this._AValue = value;
this.OnPropertyChanged("AValue");
}
}
}
private string _AValue;
protected virtual void OnPropertyChanged(string propertyName)
{
if(this.PropertyChanged != null)
this.PropertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
Example 1: simple databinding between the label and the value:
So this time, we will just bind the label to an instance of your class. We have a textbox and button that you can use to change the value of the property in MyClass. When it changes, the databinding will cause the label to be update automatically:
NOTE: Make sure to hook up Form1_Load as the load event for hte form, and UpdateValueButton_Click as the click handler for the button, or nothing will work!
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private MyClass TheClass;
private void Form1_Load(object sender, EventArgs e)
{
this.TheClass = new MyClass();
this.ValueLabel.DataBindings.Add("Text", this.TheClass, "AValue");
}
private void UpdateValueButton_Click(object sender, EventArgs e)
{
// simulate a modification to the value of the class
this.TheClass.AValue = this.NewValueTextBox.Text;
}
}
Example 2
Now, lets bind the value of class directly to the textbox. We've commented out the code in the button click hander, and we have bound both the textbox and the label to the object value. Now if you just tab away from the textbox, you will see your changes...
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private MyClass TheClass;
private void Form1_Load(object sender, EventArgs e)
{
this.TheClass = new MyClass();
// bind the Text property on the label to the AValue property on the object instance.
this.ValueLabel.DataBindings.Add("Text", this.TheClass, "AValue");
// bind the textbox to the same value...
this.NewValueTextBox.DataBindings.Add("Text", this.TheClass, "AValue");
}
private void UpdateValueButton_Click(object sender, EventArgs e)
{
//// simulate a modification to the value of the class
//this.TheClass.AValue = this.NewValueTextBox.Text;
}
Example 3
In this example, we won't use databinding at all. Instead, we will hook the property change event on MyClass and update manually.
Note, in real life, you might have a more specific event than Property changed -- you might have an AValue changed that is only raised when that property changes.
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private MyClass TheClass;
private void Form1_Load(object sender, EventArgs e)
{
this.TheClass = new MyClass();
this.TheClass.PropertyChanged += this.TheClass_PropertyChanged;
}
void TheClass_PropertyChanged(object sender, PropertyChangedEventArgs e)
{
if (e.PropertyName == "AValue")
this.ValueLabel.Text = this.TheClass.AValue;
}
private void UpdateValueButton_Click(object sender, EventArgs e)
{
// simulate a modification to the value of the class
this.TheClass.AValue = this.NewValueTextBox.Text;
}
}
There's no reason why you can't have multiple instances of a form, but in this case you want to pass the Class1 instance to the form you have. The easiest way is to add a property to Form1 and have that update the label text:
public class Form1 : Form
{
public Class1 Data
{
set
{
this.label.Text = value.LabelText;
}
}
}
Events and delegates are what you want to use here. Since you tagged this as beginner, I will leave the implementation as an exercise :), but here is the general idea:
Declare an event/delegate pair in your data class.
Create a method in your form to bind to the event.
When "something" happens in your data class, fire the event
The form's method will be invoked to handle the event and can update widgets appropriately
Good luck.

Categories