C# using an int value after triggering an event
I came to the same question again and again. I need to use the user entered values after a button event, or a doubleclick, or anything. when I do it with the designer, it passes automatically the txt control and its value to the whole program, and I can use it anywhere. But programatically I couldn't solve it. here's a little example:
private void Form1_Load(object sender, EventArgs e)
{
string blabla = "anything";
Button btn = new Button();
btn.Location = new Point(10, 40);
btn.Text = "Click me";
btn.Click += new EventHandler(btn_Click);
this.Controls.Add(btn);
}
void btn_Click(object sender, EventArgs e)
{
MessageBox.Show(blabla);
}
this doesn't work, so I added a "public" and the script goes:
public string blabla;
private void Form1_Load(object sender, EventArgs e)
{
blabla = "anything";
Button btn = new Button();
btn.Location = new Point(10, 40);
btn.Text = "Click me";
btn.Click += new EventHandler(btn_Click);
this.Controls.Add(btn);
}
void btn_Click(object sender, EventArgs e)
{
MessageBox.S开发者_运维技巧how(blabla);
}
And so I can use my variable with the changed values. This goes well with controls too. This works, but this makes thousands of public variables in a bigger application. How can I increase the readability by losing these publics? Is there a way to use "ref"? I saw it on the automatic "extract method", I just don't know, how can I use that with events.
Maybe I am on the wrong track in this, if there is a shortcut or other solution, please help.
The important change between the two snippets wasn't the fact that you made the variable public - it's that you changed it from a local variable in the Form1_Load
method into an instance variable. It can still be a private instance variable, if you're handling it in the same class.
However, another alternative is to keep it as a local variable but use an anonymous function to handle the event:
private void Form1_Load(object sender, EventArgs e)
{
string blabla = "anything";
Button btn = new Button();
btn.Location = new Point(10, 40);
btn.Text = "Click me";
btn.Click += (sender, args) => {
MessageBox.Show(blabla);
// Other code here, but hopefully not too much...
};
this.Controls.Add(btn);
}
(As noted, you don't want to make the anonymous function too big, for the sake of readability - but it can always call another method with all the appropriate state.)
EDIT: As you're using VS2005, you're only using C# 2 so you can't use lambda expressions. You can use anonymous methods though. The code would then be:
private void Form1_Load(object sender, EventArgs e)
{
string blabla = "anything";
Button btn = new Button();
btn.Location = new Point(10, 40);
btn.Text = "Click me";
btn.Click += delegate {
MessageBox.Show(blabla);
// Other code here, but hopefully not too much...
};
this.Controls.Add(btn);
}
All winforms controls tend to have a Tag
property, of type object
which you can use to store your own custom data if you wish. Its not particularly good practice, and shows up some other architectural problems but here you go:
private void Form1_Load(object sender, EventArgs e)
{
Button btn = new Button();
btn.Location = new Point(10, 40);
btn.Text = "Click me";
btn.Click += new EventHandler(btn_Click);
btn.Tag = "blahblah";
this.Controls.Add(btn);
}
void btn_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
MessageBox.Show(btn.Tag.ToString());
}
You can do it with lambdas.
btn.Click += (sender, e) => { MessageBox.Show(blabla); }
You can do it my making a closure inside the Form1_Load method like this
private void Form1_Load(object sender, EventArgs e)
{
blabla = "anything";
Button btn = new Button();
btn.Location = new Point(10, 40);
btn.Text = "Click me";
btn.Click += (s,e) => MessageBox.Show(blabla);
this.Controls.Add(btn);
}
Even if blabla
goes out of scope, the closure will still know that it contained the text "anything" when you click the button.
精彩评论