public int loses value after an action is completed - c#

My int, which is declared in a seperate class in dataStorage.cs, loses its value after this action is done:
private void button1_Click(object sender, EventArgs e)
{
dataStore dataStore = new dataStore();
dataStore.position = Convert.ToInt32(numericUpDown1.Value);
} // <= right here the value is reset to 0
what I am trying to do is, passing values between forms. but when the other form starts its process my dataStorage.position loses its value and resets to "0".
How can I properly pass values between forms?

This is because you are creating a local storage variable, which immediately goes out of scope.
Declare it as part of the form class:
public class MyForm : Form
{
public dataStore _dataStore = new dataStore();
public MyForm() { }
private void button1_click(Object sender, EventArgs e)
{
_dataStore.position = Convert.ToInt32(numericUpDown1.Value);
}
}

You haven't done anything with dataStore. It sounds like you're wanting to set the value of position for an instance of dataStorage that you're not actually using. You need to set the instance of dataStorage to the instance you create in that button for it to retain its value.

This behavior is actually expected.
When you instantiate an object, it has scope only in the context it was created in.
private void button1_Click(object sender, EventArgs e)
{
dataStore dataStore = new dataStore();
dataStore.position = Convert.ToInt32(numericUpDown1.Value);
} // When this function returns, dataStore no longer exists!
In this case, your dataStore object only exists inside of the button click handler.
What you want to do is declare the DataStore as a private member of your class, and then assign the value in the click handler.
private dataStore dataStore = new dataStore();
private void button1_Click(object sender, EventArgs e)
{
dataStore.position = Convert.ToInt32(numericUpDown1.Value);
} // <= right here the value is reset to 0
Also the actual class name in C# should have a capitalized letter for each word (PascalCase), not lowercase first letter followed by capitalized for remaining words (camelCase):
class DataStore { }
...
private DataStore dataStore = new DataStore();

You don't persist the value in any lasting location. Here's an explanation of what you're doing:
private void button1_Click(object sender, EventArgs e)
{
// You've called a function, in this case a click handler
// Here you create an instance of `dataStore`
// This instance exists *only* within the scope of this function
dataStore dataStore = new dataStore();
// Here you set a value on that instance
dataStore.position = Convert.ToInt32(numericUpDown1.Value);
}
// Now that the function has ended, any variables which were declared
// within the scope of the function are now out of scope, and removed
// from memory.
What's not clear from this code is how the value should be persisted. There are many options:
Declare the value as static, in which case you don't need to create a new instance. A static value would be available anywhere in the code.
Store the value in some persistence medium, such as a database. Basically you'd commit your dataStore object to persistence and retrieve it somewhere else.
Pass your dataStore instance as a method argument to whatever you're calling next.
Declare dataStore as a class-level member for this form and reference it in the other method.
It's likely (but, again, we can't know for sure from this code) that you want the fourth option. Which would look something like this on your form:
public class YourForm : Form
{
private dataStore dataStore = new dataStore();
private void button1_Click(object sender, EventArgs e)
{
dataStore.position = Convert.ToInt32(numericUpDown1.Value);
}
private void YourOtherMethod()
{
// dataStore.position will have a value after the button
// click handler is executed
}
}
The main point here is to think in terms of object instances. Think of a class as a "blueprint" for an object. When you create a new object, you're building an instance based on that blueprint. That instance is now unique in the system, and if you need to access it elsewhere in the code then that instance needs to be passed around the system in some way.

Related

How do I pass variables between methods in C#? [duplicate]

This question already has answers here:
Use a variable from another method in C#
(2 answers)
Closed 2 years ago.
I am trying to build a program, but I realized I can't access a certain variable because it's created in another method.
How do I transfer a variable to another method?
This is an example of what I'm trying to do:
namespace Example
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
string text = textBox1.Text;
}
private void label1_Click(object sender, EventArgs e)
{
// Get the "text" variable and use it
label1.Text = text;
}
}
}
Your example has a Form named Form1 that has a Button named button1, a TextBox named textbox1 and a Label named label1.
The scenario you are attempting is:
user enters some text into textbox1
user clicks on button1, this will save the current value from textbox1
user clicks on label1, this will display the value that was stored in the previous step
It is important to understand that in this scenario we are not trying to pass a value between 2 methods because the button click and the label click can occur independently of each other, so really this is like the memory store (M+) and memory recall (MR) buttons on calculator.
To achieve this storage you should create an instance variable (sometimes referred to as a member variable) on the Form1 class, this will be accessible to the other methods on the same instance of the Form1 class.
See Working with Instance and Local variables for a practical explanation
Create a field or a property to store the value, for your specific example either would work, however to become familiar with C# techniques I would recommend you start with a property, as that better encapsulates your scenario of storing the value for later use and later to potentially augment how and where the value is actually stored.
See What is the difference between a field and a property?
for a healthy discussion
Until you need to change the implementation, you can simply use an Auto-Property
public string StoredText { get; set; }
Now in the click event handler of button1 we can set the value of the StoredText property on the Form1 instance
private void button1_Click(object sender, EventArgs e)
{
this.StoredText = textBox1.Text;
}
set is a term we use for saving a value into a property in c#
Note the use of the this keyword, it is optional in this case, or can be inferred by the compliler, it indicates that we want to reference a member on the instance of the class, not a variable that might have the same name within the same method scope of the line of code that is executing.
Finally in the click event handler of label1 we can get the value that was previously stored in the StoredText property in the Form1 instance.
private void label1_Click(object sender, EventArgs e)
{
// Get the "StoredText" variable and use it
label1.Text = this.StoredText;
}
get is a term we use for accessing a value from a property in c#
this is not required, but can be helpful to understand that we are accessing a member that is outside of the current method scope.
Together this looks something like:
namespace Example
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
/// <summary>Saved value from see <see href="textBox1"/></summary>
public string StoredText { get; set; }
private void button1_Click(object sender, EventArgs e)
{
this.StoredText = textBox1.Text;
}
private void label1_Click(object sender, EventArgs e)
{
// Get the "StoredText" variable and use it
label1.Text = this.StoredText;
}
}
}
What you may not have noticed is that textBox1 and label1 are themselves infact instance variables that are initialized in a separate code file when InitializeComponent() is executed in the constructor.
For this reason you do not need to store the value at all and you could simply re-write the client event handler for button1 to write directly to label:
label1.Text = textBox1.Text;
It is possible to pass variables directly between methods without an intermediary store, this is a lesson for another day and will involve return statements and/or parameters on your methods.
In this scenario however, neither return or additional parameters on these methods cannot be used because these are event handlers that need a specific method signature to operate as expected.
You are almost there. It is a common practice in object-oriented programming to have private variables in a class, in order to share states. Add a variable in your class. It will be available in all methods and can be used to shared data between them (this is one approach of many):
namespace Example
{
public partial class Form1 : Form
{
private string inputText { get; set; }
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
inputText = textBox1.Text;
}
private void label1_Click(object sender, EventArgs e)
{
// Get the "text" variable and use it
label1.Text = inputText;
}
}
}

c# winforms array items gets deleted

I know this might look silly but I got a strange problem in my winforms. I have a windows application in which after a particular set of operations are completed I want to populate a Checked ComboBox. I am doing this using two classes. I want to copy a array from helper class to the form class. Array gets copied when AddArrayItems method is called. But when I see the ComboBox in the form, its null. After debugging with watch variables I got to know that the problem is after copying the array to Form1 array, as soon the control goes back to the caller, the array items are deleted. I tried to replicate my stuff, not exactly but still similar to what I am doing.
My code looks like this:
using System;
using System.Windows.Forms;
namespace DemoApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
string[] cboxAr;
public void AddCmboBoxItems(string[] cbArry)
{
cboxAr = new string[cbArry.Length];
Array.Copy(cbArry, 0, cboxAr, 0, cbArry.Length);
//cbArry.CopyTo(cboxAr, 0);
//foreach (string s in cboxAr)
//comboBox1.Items.Add(s);
comboBox1.Show();
}
private void button1_Click(object sender, EventArgs e)
{
HelperClass.DoSomething();
}
}
public class HelperClass
{
public HelperClass()
{
}
public void HelperMethod()
{
SomeMethod();
}
private void SomeMethod()
{
string[] partnrName = new string[5] { "str1", "str2", "str3", "str4", "str5"};
Form1 f = new Form1();
f.AddCmboBoxItems(partnrName);
}
public static void DoSomething()
{
new HelperClass().HelperMethod();
}
}
}
I don't understand what exactly the problem is here. Can anyone please push me in the right direction. Thanks in advance.
You're never showing the form after modifying its controls:
Form1 f = new Form1();
f.AddCmboBoxItems(partnrName);
But you're calling this from within an existing form:
private void button1_Click(object sender, EventArgs e)
{
HelperClass.DoSomething();
}
Presumably you want to modify the controls on that form? Then you'll need a reference to that form. Pass one to the method:
private void button1_Click(object sender, EventArgs e)
{
HelperClass.DoSomething(this);
}
And accept it in the method definition:
public static void DoSomething(Form1 form)
{
new HelperClass().HelperMethod(form);
}
And so until the point where you need to use it. (Side note: You have a lot of weird indirection happening here with a seemingly random mix of static and instance methods and classes. You can simplify a lot, which will make this involve fewer code changes.)
Ultimately, SomeMethod needs the instance of the form to modify:
private void SomeMethod(Form1 form)
{
string[] partnrName = new string[5] { "str1", "str2", "str3", "str4", "str5"};
form.AddCmboBoxItems(partnrName);
}
To illustrate the overall point, consider an analogy...
A car rolls off of an assembly line. You open the trunk and put a suitcase inside. Moments later another car rolls off of the same assembly line. It is identical to the first car in every way. When you open the trunk of the second car, do you expect to find your suitcase inside it?
A Form is an object like any other. Changes made to one instance of an object are not reflected in other instances of the same object. Each instance maintains its own state. In order to modify a particular instance, you need a reference to that instance.

Access object from another button click event [duplicate]

This question already has answers here:
The name 'str' does not exist in the current context
(2 answers)
Use a variable from another method in C#
(2 answers)
Closed 5 years ago.
I'm fairly new to C# so this might be pretty simple actually though I have spent a couple hours searching without a solution.
I'm working with windows form and I am trying to access an object from another button-click event. The error I'm getting is "The name 'object' does not exist in the current context" when trying to access object in Button2_Click.
public void Button1_Click(object sender, EventArgs e)
{
// Prefilled with a persons info
MyClass object = new MyClass();
}
public void Button2_Click(object sender, EventArgs e)
{
// Access object
string name = object.Name;
}
So my question is how do I access an object created in another "Button_Click"?
A couple of issues exists.
You can't use object as variable name. (object is a reserved keyword)
You can't access a internal variable, within another event.
To solve your issue, you would scope the variable when your initial object is created.
public class Example
{
// Variable declared as a class global.
private readonly Sample sample;
// Constructor to build our sample.
public Example() => sample = new Sample();
// Button writing a property from sample.
protected void btnSend(object sender, EventArgs e) => Console.WriteLine(sample.SomeProperty);
}
So the object is in the upper portion of your class, when you build Example, a sample is always created. So as you utilize Sample within your Example class, it will be correctly scoped.
I also don't understand why you have to click one button, to populate this object, so I altered to have the object built once Example is created.
The scope of the object should be class level in order to be used by other methods in the same class:
private MyClass _myClassObject; // class level object. Remember "object" is reserved keyword that is why renamed it to "_myClassObject"
public void Button1_Click(object sender, EventArgs e)
{
// Prefilled with a persons info
_myClassObject = new MyClass();
}
public void Button2_Click(object sender, EventArgs e)
{
// Access object
string name = _myClassObject.Name;
}

How do I change the value of form controls without triggering any event?

I want to change the value that is assign to control of a form in c# (visual studio 2010), while the form is loaded.
I want my form should display to the end user, but at the same time as I get the data from server, I want it to reflect the same data onto the controls. (without any using timer, thread or any event).
Example : textBox1.text ="abc";
if server is sending "xyz" than while form is already loaded testbox's value should automatically change to xyz.
without any click or any kind of event.
You have to look at how Properties in c# work:
If we decompile a simple class on sharplab.io
public class C {
public int foo
{get;set;}
}
You will see that the compile will always generate backing fields and a getter and setter method.
So if you don't want to trigger an event you will have to bypass these methods as most likely the event will be triggered in there.
This should be doable with an reflection which is normally pretty easy to do.
BUT Textbox doesn't seem to have a backing field which is easily accessible for its Text-Property. Most likely it is set by its private StringSource field. Which is from the internal type StringSource. So first we have to get the type. Get a reference to the constructor then call this and set the private field.
This is how far i've come:
private int number = 0;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
number++;
this.textBox1.Text = number.ToString();
}
private void button2_Click(object sender, EventArgs e)
{
number++;
Type cTorType = typeof(string[]);
string[] cTorParams = new string[] { number.ToString() };
Type type = this.textBox1.GetType().GetRuntimeFields().ElementAt(11).FieldType;
ConstructorInfo ctor = type.GetConstructor(new[] { cTorType });
object stringSourceInstance = ctor.Invoke(new[] { cTorParams });
this.textBox1.GetType().GetRuntimeFields().ElementAt(11).SetValue(this.textBox1, stringSourceInstance);
}
private void textBox1_TextChanged(object sender, EventArgs e)
{
MessageBox.Show("Changed!");
}
I'd recommend digging a bit more into reflection and see what you can find in the TextBox class by using typeof(TextBox).GetFields / .GetProperties because somewhere there must be a field or property which you can change to bypass your setter method triggering the event.
Hope this helps.

Passing object to different windows forms

I want to pass a C# object between win forms. At the moment, I have setup a basic project to learn how to do this which consists of two forms - form1 and form2 and a class called class1.cs which contains get and set methods to set a string variable with a value entered in form1. (Form 2 is supposed to get the value stored in the class1 object)
How can I get the string value from the object that was set in form1? Do I need to pass it as a parameter to form2?
Any comments/help will be appeciated!
Thanks,
EDIT: Here's the code I have at the moment: (form1.cs)
private void button1_Click(object sender, EventArgs e)
{
this.Hide();
Form2 form2 = new Form2();
form2.Show();
}
private void button2_Click(object sender, EventArgs e)
{
if (textBox1.Text != "")
{
Class1 class1 = new Class1();
class1.setStringValue(textBox1.Text);
}
}
}
}
There are a few different ways to do this, you could use a static class object, the above example would be ideal for this activity.
public static class MyStaticClass
{
public static string MyStringMessage {get;set;}
}
You don't need to instance the class, just call it
MyStaticClass.MyStringMessage = "Hello World";
Console.WriteLine (MyStaticClass.MyStringMessage);
If you want an instance of the object you can pass the class object that you create on Form1 into Form2 with the following.
private void button1_Click(object sender, EventArgs e)
{
this.Hide();
Form2 form2 = new Form2();
form2.MyClass = class1;
form2.Show();
}
Then create a property on Form2 to accept the class object.
public Class1 MyClass {get;set;}
remember to make the Class1 object a global variable rather than create it within button 2 itself.
Yes, in Form1 you declare an instance of Class1 and then set the parameters as needed, then you pass it to Form2. You could for example have a constructor in Form2 and have a Class1 parameter in it. Assuming that Form1 creates Form2, otherwise you have to have some way for Form1 to find Form2 to pass the instance across.
Since I have been working in ASP.Net the last couple years I have found myself working with Newtonsoft.Json a lot. Turns out to be great within WinForms too, and in this case seemed to simplify passing objects between forms... even complex ones are a breeze!
The implementation is like this:
// Set Object Property within Form
public partial class FlashNotify : Form
{
public string Json { get; set; }
}
On the form load event you can then grab your object:
private void FlashNotify_Load(object sender, EventArgs e)
{
// Deserialize from string back to object
CommUserGroupMessage msg = new CommUserGroupMessage();
msg = Newtonsoft.Json.JsonConvert.DeserializeObject<CommUserGroupMessage>(Json);
}
Lastly is passing the object to the form:
// Serialize the Object into a string to pass
string json = Newtonsoft.Json.JsonConvert.SerializeObject(msg);
FlashNotify fn = new FlashNotify();
fn.Json = json;
fn.Show();
Granted the original selected answer is probably easier, however I like this approach as it avoids the need to replicate the class within your form, which I think makes it easier to maintain (Correction: Miss correctly read the static class in the example, I at first thought it was replicated within the form).
Using Delegate you can easily pass data to a form.
Technically, a delegate is a reference type used to encapsulate a method with a specific signature and return type
Step 1
Add a delegate signature to form1 as below:
public delegate void delPassDataToFrom(Object obj);
Step 2
In form1’s any button click event handler, instantiate form2 class and delegate. Assign a function in form2 to the delegate and call the delegate as below:
private void btnSend_Click(object sender, System.EventArgs e)
{
Form2 frm = new Form2();
delPassDataToFrom del = new delPassDataToFrom(frm.retrieveData);
del(objectToPass);
frm.Show();
}
Step 3
In form2, add a function to which the delegate should point to. This function will use the object passed:
public void retrieveData(Object objPassedFromParent)
{
//use the objPassedFromParent object as needed
}

Categories

Resources