This is my first question here and, although it's probably a very nooby one, it's had me stumped for quite a while. I'm using a simplified example to explain.
On a Console Application, I have a public int 'x' set to 0 and a method 'test' which changes it to 1. When 'test' is called in Main, the value of X is now 1 (as expected).
public int x = 0;
public void test()
{
x = 1;
}
static void Main(string[] args)
{
Program program = new Program();
program.test();
Console.WriteLine(program.x);
Console.ReadLine();
}
However (and this is what I don't understand), when using a button_Click event to call the same 'test' method on a Windows Form Application, 'x' remains as 0:
public Form1()
{
InitializeComponent();
}
public int x = 0;
public void test()
{
x = 1;
}
private void button1_Click(object sender, EventArgs e)
{
Form1 form = new Form1();
form.test();
MessageBox.Show("" + x);
}
}
So to summarize, what I am wanting to happen is for 'test' to be called when the button is clicked, changeing the value of 'x' to 1. Can anyone explain why this isn't working?
Thanks!
You've create two separate instances of Form1. Calling the test() method on the second instance is not going to affect the value of x in the first instance.
Change the button click event, so that you're not creating a new Form1.
private void button1_Click(object sender, EventArgs e)
{
test(); // now it'll call test() on the current instance, and modify x as you expect
MessageBox.Show("" + x);
}
Because is happening for the form that you created with Form1 form = new Form1();
Remove that line,call only test() and try again, it should work.
Related
For example if I have a form called frmOne and I am there and I do some things then click a button event and it goes and takes me to a second form called frmTwo. Then I am in frmTwo and I do some things then I click a button in frmTwo and this button creates a new instance of frmOne. Since now I have two forms of frmOne open what will Visual Studios call the second instance of frmOne. I need to figure this out because I need to access it in code. I have tried using frmOne as the name to reference it in code but it doesnt work on the second instance. Any ideas how I can find this name or what Visual Studios calls it? I am assuming Visual Studios does something like calling the second instance frmOne1 or something like that. Thanks in advance.
From the example above here below frmShoppingCart is my first form. I have two instances of it open. I am trying to close the second instance from the closing event of another form. I can close the first instance with the code below and I can use it to close the second instance if I knew what the name was of the second instance which I am assuming is different from frmShoppingCart. I just am assuming Visual Studios is calling the name of my second instance of frmShoppingCart something else than frmShoppingCart.
private void frmViewer_FormClosing(object sender, FormClosingEventArgs e)
{
//close shopping cart form and refresh and open the shop now form
frmShoppingCart obj = (frmShoppingCart)Application.OpenForms["frmShoppingCart"];
obj.Close();
}
It's not clear why you need to reference a form indirectly by name. You could instead hold a reference directly to the form.
If you still want to reference by name, you can, but you need some other piece of data to disambiguate the form as #Steve said in the comments. To do that you could add another property to the form. Here's a small demo form
public partial class Form1 : Form
{
public Form1() => InitializeComponent();
private void button1_Click(object sender, EventArgs e)
{
var f = new Form1 { Instance = ++Counter };
f.ShowDialog();
}
private void button2_Click(object sender, EventArgs e)
{
var forms = Application.OpenForms;
}
public int Instance { get; set; }
public static int Counter { get; set; }
}
that shows, under the debugger with a breakpoint after
var forms = Application.OpenForms;
that you can see the disambiguation.
Note that searching by name alone will return the first form with that name. To get the correct one, do a search using linq against Application.OpenForms (again, credit #Steve):
var myForm = Application.OpenForms
.FirstOrDefault(x => x.Name == "Form1" && x.Instance == 1);
This is but one way to find the form. You could instead change Name when you create the form. Here's an example using the Counter above.
private void button1_Click(object sender, EventArgs e)
{
var f = new Form1();
f.Name += ++Counter;
f.ShowDialog();
}
This gives us
You can use Singleton to have a list of named Forms opened from the first ...
public partial class Form1 : Form {
public FormsOpened Forms => FormsOpened.Instance;
public Form1() {
this.InitializeComponent();
}
protected override void OnLoad(EventArgs e) {
base.OnLoad(e);
for (int i = 0; i < 10; i++) {
var f = default(Form);
// Form2 is a simple empty form
this.Forms.formsOpened.Add(f = new Form2() { Name = "Pippo" + i });
f.Show();
}
}
protected override void OnClosing(CancelEventArgs e) {
base.OnClosing(e);
foreach (var f in this.Forms.formsOpened) {
f.Close();
}
}
}
public sealed class FormsOpened {
private static FormsOpened instance = null;
public List<Form> formsOpened = new List<Form>();
private int counter = 0;
public static FormsOpened Instance {
get {
if (instance == null) {
instance = new FormsOpened();
}
return instance;
}
}
private FormsOpened() {
this.counter++;
}
}
In this way in every class you want you can access the FormsOpened Forms => FormsOpened.Instance and use it ;)
How would I share variables between "Click on a button" functions inside a WinForms application? I tried reading about it, but I'm quite new to this and didn't really get it clear - from what I understand, I have to use the static keyword?
I don't really know how to explain it, so I'll just show some simple code (that has mistakes in it, since I don't know how to make it work):
namespace stackoverflow
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
label1.Text = "Not clicked!";
int number = 0;
}
private void label1_Click(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "Clicked button 1.";
number = 1;
}
private void button2_Click(object sender, EventArgs e)
{
label1.Text = "Clicked button 2.";
number = 2;
}
}
}
How would I make the number actually update in the whole class...?
They don't have to be static since you're using the same instance of the Form1 class. Since the event handlers are properties of the form and not the buttons, you can use form-level member form all event handlers:
public partial class Form1 : Form
{
private int number = 0; // field at the form level
public Form1()
{
InitializeComponent();
label1.Text = "Not clicked!";
}
private void label1_Click(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "Clicked button 1.";
number = 1;
}
private void button2_Click(object sender, EventArgs e)
{
label1.Text = "Clicked button 2.";
number = 2;
}
}
It helps when you understand what the accessibility types mean.
When something is declared as static, it means that the variable occupies a single place in memory for the lifetime of the application. Calling or assigning to that variable will only ever affect a single memory location/offset.
Non-Static variables are, as you say, 'members' of an instance of a type.
The difference in how they are accessed is that you would need to prefix the variable with the instance of the class which contains the variable.
theFormInstance.Number = 5;
or
this.Number=5;
Static variables however, are referenced by using the type name.
I like to think of it as 'belonging'
A static variable 'belongs to the type' where a non-static 'belongs to an instance of the type'
Form1.Number= 5;
While yes, you can use Static variables, you shouldn't need to in this particular example because the variable you are attempting to alter resides within the same Form class as the click events.
As long as the variable is declared outside of the click event handlers/methods, but within the enclosing class - then all methods within the Form1 class will have access to the variable.
Note - I suspect that because you were clicking on buttons, you assumed that the buttons wouldn't have visibility to the form class, because they are other controls etc.
The thing to remember is that while the buttons are triggering the event handler 'click' to execute, it is still the Form that is running the code.
Eg:
MessageBox.Show(this.Name);
This will return the Form's name, no matter where you execute it within the Form, whether it be in a buttons click event or in a form load event.
If you wanted to grab the button from inside an event handler, then you could use the 'sender' variable to reference the button.
(You would need to cast it to the proper type though.
Eg
private void button2_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
label1.Text = "Clicked "+btn.Name;
number = 2;
}
Anyway, know this goes off in a few directions, but hope its informative and gives you an insight into accessibility within forms.
Just remember - Controls live within the Form, so they have equal access to all variables declared within the form - as long as they are inside the form but outside of method bodies.
You have the same instance of the class. There's no need to use static, all you need is a simple field, rather than using a local:
public partial class Form1 : Form
{
int number;
...
}
Put the int number = 0; in the class declaration and not in the constructor. (E.g. put it between the public Form1() and public partial class Form1 { lines)
Basically to regurgitate what everyone else is saying:
Either create a class and work directly from that that contains your properties and fields, pass that between your forms. I wouldn't put a field/property anywhere in your Form.cs except the top, just to keep it clean really. I would check out WPF and the MVVM pattern to be honest, this is where it excels at and it's really the future. I went the route of Winforms/WebForms and now only develop using WPF/MVC and really wish I would have just skipped the other stuff. Just my two cents to be honest.
Initialize the number outside form function like
namespace stackoverflow
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
label1.Text = "Not clicked!";
}
int number = 0;
private void label1_Click(object sender, EventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = "Clicked button 1.";
number = 1;
}
private void button2_Click(object sender, EventArgs e)
{
label1.Text = "Clicked button 2.";
number = 2;
}
}
}
Declare the variable at class level rather than locally.
public partial class Form1 : Form
{
int number = 0;
public Form1()
{
...
I'm starting to think this is a stupid question, because I cannot find anything related but here goes.
So I've been learning C# and trying to figure out methods, so I created a simple method that increases a variable when used. So then I attached it to a button in Microsoft Visual Forms. However it only seems to increase the value once and then the computer stops executing the method.
Here's My Code
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int number = 0;
public void button1_Click(object sender, EventArgs e)
{
NumberMethod(number);
}
public int NumberMethod(int number)
{
number++;
label1.Text = number.ToString("Number:#");
return number;
}
}
So again I want it to execute the method and increase the variable every time someone clicks the button.
Try using this keyword:
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
int number = 0;
public void button1_Click(object sender, EventArgs e)
{
NumberMethod();
}
public int NumberMethod()
{
this.number++;
label1.Text = this.number.ToString("Number:#");
return this.number;
}
}
Explanation:
When you invoke NumberMethod(number) it passes only the value which is initially zero. And that is incremented by 1 from the function. The important thing is the value of the variable number is not changed yet (it remains zero). The same happens again and again.
In my solution, we are not passing the value, but changing the value of number from the method itself.
So, huh, I'm kinda new to programming in general and I have a questions that maybe you could help me out. I don't know if I did this right but hope you can give me a light here.
public partial class Form1 : Form
{
private int tick;
private int conta_jogadas;
private string[,] grelha = new string[3,3];
public Form1()
{
InitializeComponent();
}
private void pos00_button_Click(object sender, EventArgs e)
{
if (tick == 0)
{
pos00_button.Text = "X";
tick = 1;
}
else if (tick == 1)
{
pos00_button.Text = "O";
tick = 0;
}
grelha[0, 0] = pos00_button.Text;
conta_jogadas++;
}
And to verify it I have:
private void Form1_Load(object sender, EventArgs e)
{
if (conta_jogadas == 1)
{
MessageBox.Show("Teste");
}
}
For the moment I just want my button to add 1 to my variable. If i click it 3 times, my conta_jogadas will be = 3. I think I was clear here, don't know what else I can add to help. Well, thanks in advance guys.
This function
private void Form1_Load(object sender, EventArgs e)
{
if (conta_jogadas == 1)
{
MessageBox.Show("Teste");
}
}
Will execute exactly once, when your form loads. At that time the variable conta_jogadas will have the value 0 (The default for an int) so you will not ever see your message box.
You could change this to a normal function that you call whenever you update conta_jogadas if you want to see the message box when the value becomes 1
For the moment I just want my button to add 1 to my variable. If i click it 3 times, my conta_jogadas will be = 3.
Try this:
public partial class Form1 : Form
{
private int tick;
private int conta_jogadas;
private string[,] grelha = new string[3,3];
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
if (conta_jogadas == 1)
{
MessageBox.Show("Teste");
}
}
private void pos00_button_Click(object sender, EventArgs e)
{
conta_jogadas++;
grelha[0, 0] = pos00_button.Text;
}
}
Every time button: pos00 gets clicked, variable conta_jogadas gets 1 added to the current number.
Note: couldn't compile since, I don't have Visual Studio installed here...
I've stomped with a problem I've spent some hours trying to solve, with my very limited knowledge.
I have a listview in my form1 called listMachine
And I have a method in form1.cs such as
private void máquinaToolStripMenuItem_Click(object sender, EventArgs e)
{
machinename open = new machinename();
open.Show();
}
machinename.cs is another form, and I use that method to open my other form, with an object called open.
the machinename button is a simple form which just serves as an input receiver, it asks a name, we have to type it into the textbox, press a button and it receives the input.
This is the code that runs when you press the button
public void buttonAceitarnome_Click(object sender, EventArgs e)
{
if (textBoxnomenova.TextLength == 0)
{
toolTipEmptyname.Show("O nome da máquina não pode estar vazio", textBoxnomenova);
}
else
{
Variables.var = textBoxnomenova.Text;
//MessageBox.Show(Variables.var); debug purpose, the messagebox does carry variables.var text
obj.listMachine.Items.Add(Variables.var); //If I change the variables.var to "test" it will NOT add the item.
this.Close();
}
}
Also, I forgot to mention my Variables.cs class, I created it because it was the only way I found to pass variables from a class to another (machinename.cs to form1.cs), but still, the items are not added into the listview.
This is my variables.cs code
public static class Variables
{
public static string var;
}
The comments I added to the code also give you some extra debug info..
I didn't want to ask for online help, but couldn't solve this on my own :(
If I were you, I would first remove the Variables class.
Then, you'r first form/class is called obj.cs, am I right? Or is it form1.cs?
I made it look like this:
public partial class obj : Form
{
public static string text; //This is a variable that can be reached from
public obj()
{
InitializeComponent();
}
private void máquinaToolStripMenuItem_Click(object sender, EventArgs e)
{
machinename open = new machinename();
open.ShowDialog(); //I put ShowDialog instead of Show
addItem(); //This method is called when the showed dialog is closed (machinename.cs)
}
private void addItem()
{
listMachine.Items.Add(text);
}
}
and the machinename.cs class like this:
public partial class machinename : Form
{
public machinename()
{
InitializeComponent();
}
private void buttonAceitarnome_Click(object sender, EventArgs e) //This one can be private
{
if (textBoxnomenova.TextLength == 0)
{
//Something here
}
else
{
obj.text = textBoxnomenova.Text; //Initializing the public static variable
this.Close(); //Closes the form, next step will be to run the method in obj.cs
}
}
}
If I understood your question correctly, you wanted to add an item to the ListView called "listMachine" via a button in the form "machinename.cs". This code will do that. I hope it helps you.
Change the click event from private to protected.
protected void máquinaToolStripMenuItem_Click(object sender, EventArgs e)