Getting values from buttons created runtime in c# Winforms - c#

I am creating 2 buttons during run-time and I need to do different thing depending upon which button clicked,
following is the code, I have written for click event, however I don't know how do I code where my program understand which button is being clicked.
{
.
.
Button btn = new Button();
btn.Location = new Point(x+70,y);
btn.Height = 15;
btn.Width = 50;
Controls.Add(btn);
btn.Name = "button1";
btn.Click +=btn_Click;
btn = new Button();
btn.Location = new Point(x + 140, y);
btn.Height = 15;
btn.Width = 50;
Controls.Add(btn);
btn.Name = "button2";
btn.Click += btn_Click;
}
private void btn_Click(object sender, EventArgs e)
{
// Understand which of the buttons is clicked!
}
Any help appreciated.

Controls all have a Tag property that can have any object assigned to it. You don't even really need to use the Name property when creating the buttons programmatically. Here I've used simply strings, but any unique action the button can take can be distilled to its required elements and the things it needs to do that can be put into an object and assigned to the Tag property.
Button btn = new Button();
Controls.Add(btn);
btn.Tag = "Hello from Button #1";
btn.Click += btn_Click;
btn = new Button();
Controls.Add(btn);
btn.Tag = "Hello from Button #2";
btn.Click += btn_Click;
In the event handler you are passed the sender, which is a reference to the control that raised the event. You can then access its Tag property with a simple cast :
private void btn_Click(object sender, EventArgs e)
{
if (sender is Control) {
MessageBox.Show(((Control)sender).Tag.ToString());
}
}
To show the example that the Tag can be anything :
Button btn = new Button();
Controls.Add(btn);
btn.Tag = Color.Blue;
btn.Click += btn_Click;
btn = new Button();
Controls.Add(btn);
btn.Tag = Color.Red;
btn.Click += btn_Click;
and
if (sender is Control) {
this.BackColor = (Color)((Control)sender).Tag;
}

object sender is the object which fired the event. In your example the sender is the button clicked. So you can cast sender to Button and decide what you want to do.

Related

How can I create a button programmatically in C# window app?

In the Form1_Load method what code should I write to create a simple button?
private void Form1_Load(object sender, System.EventArgs e)
{
}
So that on Load the button would show.
As you said it is Winforms, you can do the following...
First create a new Button object.
Button newButton = new Button();
Then add it to the form inside that function using:
this.Controls.Add(newButton);
Extra properties you can set...
newButton.Text = "Created Button";
newButton.Location = new Point(70,70);
newButton.Size = new Size(50, 100);
Your issue you're running to is that you're trying to set it on Form_Load event, at that stage the form does not exist yet and your buttons are overwritten. You need a delegate for the Shown or Activated events in order to show the button.
For example inside your Form1 constructor,
public Form1()
{
InitializeComponent();
this.Shown += CreateButtonDelegate;
}
Your actual delegate is where you create your button and add it to the form, something like this will work.
private void CreateButtonDelegate(object sender, EventArgs e)
{
Button newButton= new Button();
this.Controls.Add(newButton);
newButton.Text = "Created Button";
newButton.Location = new Point(70,70);
newButton.Size = new Size(50, 100);
newButton.Location = new Point(20, 50);
}
on your eventload form put this code
private void Form1_Load(object sender, EventArgs e)
{
Button testbutton = new Button();
testbutton.Text = "button1";
testbutton.Location = new Point(70, 70);
testbutton.Size = new Size(100, 100);
testbutton.Visible = true;
testbutton.BringToFront();
this.Controls.Add(testbutton);
}
It's simple :
private void Form1_Load(object sender, System.EventArgs e)
{
Button btn1 = new Button();
this.Controls.add(btn1);
btn1.Top=100;
btn1.Left=100;
btn1.Text="My Button";
}

TextBox not activating Form accept button

I have a Form which has a TextBox and a Button. I have set the Form's AcceptButton property to my Button, and set the TextBox's AcceptsReturn property to false:
class Window : Form
{
private TextBox textBox1;
private Button btn;
public Window()
{
this.Size = new Size(200, 200);
this.AcceptButton = this.btn;
textBox1 = new TextBox();
textBox1.Location = new Point(10, 10);
textBox1.Width = 50;
textBox1.AcceptsReturn = false;
this.Controls.Add(textBox1);
btn = new Button();
btn.Text = "Test";
btn.Location = new Point(textBox1.Right + 10, 10);
btn.Click += btn_Click;
this.Controls.Add(btn);
}
void btn_Click(object sender, EventArgs e)
{
MessageBox.Show("Works");
}
}
class Program
{
static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.Run(new Window());
}
}
However, when pressing the Enter key while the TextBox has focus, the AcceptButton of the Form is not activated. I worked around it using the KeyDown event of the TextBox like so:
textBox1.KeyDown += (s,e) => { if (e.KeyCode == Keys.Enter) btn.PerformClick(); } ;
And although it works I am curious as to why the earlier method using the AcceptButton property failed.
The problem is that you set the Form's AcceptButton to btn before you instantiate it. Move this.AcceptButton = this.btn; to any line AFTER btn = new Button();.. btn is pointing to a null reference up until new Button(). Once you instantiate btn you can use it to set AcceptButton.
You just wrote one line in the wrong place.That's the answer:
public Form1()
{
InitializeComponent();
this.Size = new Size(200, 200);
textBox1 = new TextBox();
textBox1.Location = new Point(10, 10);
textBox1.Width = 50;
textBox1.AcceptsReturn = true;
this.Controls.Add(textBox1);
btn = new Button();
btn.Text = "Test";
btn.Location = new Point(textBox1.Right + 10, 10);
btn.Click += btn_Click;
this.Controls.Add(btn);
this.AcceptButton = this.btn;
}
I hope this helps you!

How do I detect hold event for a button?

I would like to add an hold gesture to a C# created button. But all solution that I've found on the internet don't work. I post the part of the code involved the creation of the button:
var button = new Button();
button.Click += new RoutedEventHandler(ButtonClickOneEvent);
button.Hold += new TypedEventHandler<GestureRecognizer, HoldingEventArgs>(holder_recon);
The button.Hold doesn't work and it gives me an error.
For now, I want holder_recon, the function that should start when the button is held, give execute MessageBox.Show("Held").
Can you please help me?
May this will help you.
var button = new Button();
button.VerticalAlignment = System.Windows.VerticalAlignment.Top;
button.Height = 75;
button.Tag = tag;
button.Background = new SolidColorBrush(colore);
button.HorizontalContentAlignment = System.Windows.HorizontalAlignment.Stretch;
button.Click += button_Click;
button.Hold += button_Hold;
private void button_Hold(object sender, System.Windows.Input.GestureEventArgs e) => MessageBox.Show("Hold");
private void button_Click(object sender, RoutedEventArgs e) => MessageBox.Show("Click");

WPF / C# - Adding functionality to a button dynamically created inside a listbox

I have a button that adds this StackPanel to the listbox everytime it's clicked. In it is a button. I'm trying to figure out how to add code to this button that it's adding. Ideally I want the button to be a delete button, so it would delete that element (itself) in the list. I'm just trying to figure out how to add functionality to the button I'm dynamically creating. hope that makes sense
thanks for any help!
private void Button_Click_1(object sender, RoutedEventArgs e)
{
StackPanel stackPanel = new StackPanel();
stackPanel.Orientation = System.Windows.Controls.Orientation.Horizontal;
CheckBox checkBox = new CheckBox();
checkBox.IsChecked = true;
TextBox textBox = new TextBox();
textBox.Width = 100;
textBox.Text = textBox1.Text;
Button button = new Button(); //HOW DO I ADD CODE TO THIS BUTTON?
stackPanel.Children.Add(checkBox);
stackPanel.Children.Add(textBox);
stackPanel.Children.Add(button); //HOW DO I ADD CODE TO THIS BUTTON?
listBox1.Items.Add(stackPanel);
}
You can programatically add a click handler to the button like this:
Button button = new Button(); //HOW DO I ADD CODE TO THIS BUTTON?
button.Click += btn_Click;
stackPanel.Children.Add(checkBox);
stackPanel.Children.Add(textBox);
stackPanel.Children.Add(button); //HOW DO I ADD CODE TO THIS BUTTON?
and then you need the click event handler
void btn_Click(object sender, System.Windows.RoutedEventArgs e)
{
// your code to execute when the button is clicked.
stackPanel.Items.Remove(button);
}
Try This.
Add Stackpanel that have textblock and Button
private void OnSaveClick(object sender, RoutedEventArgs e)
{
StackPanel stp = new StackPanel();
stp.Orientation = Orientation.Horizontal;
stp.Children.Add(new TextBlock()
{
Text = string.Format("Item {0}", lstitems.Items.Count),
HorizontalAlignment = System.Windows.HorizontalAlignment.Stretch
});
Button btn = new Button();
btn.Content = string.Format("Delete Item {0}", lstitems.Items.Count);
btn.Height = 25;
btn.Width = 100;
btn.HorizontalAlignment = System.Windows.HorizontalAlignment.Right;
btn.Click += btnDeleteClick;
stp.Children.Add(btn);
lstitems.Items.Add(stp);
}
Delete Button Click handler
void btnDeleteClick(object sender, RoutedEventArgs e)
{
Button btn = (Button)sender;
if (btn != null)
{
var st = FindParent<StackPanel> (btn); //stackpanel as we have added item as stackpanel.
if (st != null)
lstitems.Items.Remove(st);
}
}
To Find the Type to Object in the Visual Tree.
public T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null) return null;
var parentT = parent as T;
return parentT ?? FindParent<T>(parent);
}
That is the simplest setup. Ideally you want more error handling etc.
Button button = new Button();
button.Click += (s, args) => { listBox1.Items.Remove(stackPanel); };

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.Show(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.

Categories

Resources