Address a generated button for clickevent - c#

I have a class that creates panels with controls based on my database. It creates a panel with a button on each panel, per row in DB. How do I address one specific button to make a click event?
I'm a rookie, and maybe abit over my head, but you don't learn to swim in shallow water ;)
Any help appreciated!
while (myDataReader.Read())
{
i++;
Oppdrag p1 = new Oppdrag();
p1.Location = new Point (0, (i++) * 65);
oppdragPanel.Controls.Add(p1);
p1.makePanel();
}
class Oppdrag : Panel
{
Button infoBtn = new Button();
public void makePanel()
{
this.BackColor = Color.White;
this.Height = 60;
this.Dock = DockStyle.Top;
this.Location = new Point(0, (iTeller) * 45);
infoBtn.Location = new Point(860, 27);
infoBtn.Name = "infoBtn";
infoBtn.Size = new Size(139, 23);
infoBtn.TabIndex = 18;
infoBtn.Text = "Edit";
infoBtn.UseVisualStyleBackColor = true;
}
}

You'll need a method that matches the event thrown by clicking on the button.
i.e.)
void Button_Click(object sender, EventArgs e)
{
// Do whatever on the event
}
Then you'll need to assign the click event to the method.
p1.infoBtn.Click += new System.EventHandler(Button_Click);
Hope this helps.

You can add the event handler for the button when you create the button. You can even add a unique CommandArgument per button so you can distinguish one button from another.
public void makePanel()
{
/* ... */
infoBtn.UseVisualStyleBackColor = true;
infoBtn.Click += new EventHandler(ButtonClick);
infoBtn.CommandArgument = "xxxxxxx"; // optional
}
public void ButtonClick(object sender, EventArgs e)
{
Button button = (Button)sender;
string argument = button.CommandArgument; // optional
}

Related

When generating multiple buttons in C# how do I give each one a separate function?

In my code, I generate one extra label and button every time a different button is clicked. I want it so each button can be programmed with a different function. Ex: If I clicked on generated button1 I would be brought to page 1. If I clicked on generated button2 I would be brought to page 2 etc. What would be the best way to approach this?
Here is my code below:
if (task1 == false)
{
Label taskLabel = new Label();
taskLabel.Text = taskInput.Text;
taskLabel.Location = new Point(63, 183);
taskLabel.BorderStyle = BorderStyle.FixedSingle;
taskLabel.AutoSize = true;
page2.Controls.Add(taskLabel);
labelHeight = taskLabel.Bottom;
labelWidth = taskLabel.Right;
Button taskButton = new Button();
taskButton.Text = "Let's Go";
taskButton.Location = new Point(labelWidth + 30, 180);
taskButton.AutoSize = true;
page2.Controls.Add(taskButton);
taskInput.Text = "";
task1 = true;
}
else
{
Label taskLabel = new Label();
taskLabel.Text = taskInput.Text;
taskLabel.Location = new Point(63, labelHeight + 30);
taskLabel.BorderStyle = BorderStyle.FixedSingle;
taskLabel.AutoSize = true;
page2.Controls.Add(taskLabel);
Button taskButton = new Button();
taskButton.Text = "Let's Go";
labelHeight = taskLabel.Bottom;
labelWidth = taskLabel.Right;
taskButton.Location = new Point(labelWidth + 30, labelHeight - 18);
taskButton.AutoSize = true;
buttonHeight = taskButton.Top;
page2.Controls.Add(taskButton);
taskInput.Text = "";
After you create the button you add a handler to the function that you want it to run.
Button taskButton = new Button();
taskButton.Click += FunctionYouWantToRun();
You can set the click handler for each button you create like this
Button taskButton1 = new Button;
taskButton1.Click += taskButton1_Click;
private void taskButton1_Click(object sender, EventArgs e)
{
// code for the first button
}
Button taskButton2 = new Button;
taskButton2.Click += taskButton2_Click;
private void taskButton2_Click(object sender, EventArgs e)
{
// code for the second button
}
If you have many buttons you could assign them all the same click event and in that click event determine which button was clicked
Button taskButton1 = new Button;
taskButton1.Tag = 1;
taskButton1.Click += taskButton_Click;
Button taskButton2 = new Button;
taskButton2.Tag = 2;
taskButton2.Click += taskButton_Click;
Button taskButton3 = new Button;
taskButton3.Tag = 3;
taskButton3.Click += taskButton_Click;
private void taskButton_Click(object sender, EventArgs e)
{
if ( ((Button)sender).Tag == 1) then
{
// code for the first button
}
else if ( ((Button)sender).Tag == 2) then
{
// code for the second button
}
else if ( ((Button)sender).Tag == 3) then
{
// code for the third button
}
}
or without using the Tag property
Button taskButton1 = new Button;
taskButton1.Click += taskButton_Click;
Button taskButton2 = new Button;
taskButton2.Click += taskButton_Click;
Button taskButton3 = new Button;
taskButton3.Click += taskButton_Click;
private void taskButton_Click(object sender, EventArgs e)
{
if (sender == Button1) then
{
// code for the first button
}
else if (sender == Button2) then
{
// code for the second button
}
else if (sender == Button3) then
{
// code for the third button
}
}

Creating a dynamic button

I am trying to creat a dynamic button in a my application. So basically I have this code but when I run it I don’t see the bottom in the other form . The panel is empty. I create the bottom on a button click in a first form then it has to show the button in the second form’s panel.
private void btnsend_Click(object sender, EventArgs e)
{
this.Hide();
Form wrr = new Interface();
wrr.Show();
createnutton();
}
int i = 0;
int x = 0;
private void createnutton()
{
Button btn = new Button();
btn.Location = new Point(3 + i, 14 + x);
btn.BackColor = System.Drawing.Color.Red;
btn.ForeColor = System.Drawing.Color.Yellow;
btn.Text = "Tabel" + libtno.Text;
btn.Click += new EventHandler(btn_Click);
panel3.Controls.Add(btn);
i += 10;
x += 10;
}
void btn_Click(object sender,EventArgs e)
{
MessageBox.Show("me");
}
You have to set one more property "Visible=true" for your Button.
You need a reference to the instance of Interface that you created. Pass wrr to your createnutton function. For this to work, you have to change the MODIFIERS property of panel3 to PUBLIC. You also can't reference the Form with the generic Form type. It has to be of that specific Form type, which is Interface (a horrible name by the way, since interface has different meaning in C#):
private void btnsend_Click(object sender, EventArgs e)
{
this.Hide();
Interface wrr = new Interface();
wrr.Show();
createnutton(wrr); // <-- pass "wrr" to the function
}
int i = 0;
int x = 0;
private void createnutton(Interface frmInterface) // <-- parameter added
{
Button btn = new Button();
btn.Location = new Point(3 + i, 14 + x);
btn.BackColor = System.Drawing.Color.Red;
btn.ForeColor = System.Drawing.Color.Yellow;
btn.Text = "Tabel" + libtno.Text;
btn.Click += new EventHandler(btn_Click);
frmInterface.panel3.Controls.Add(btn); // <-- use the passed in form
i += 10;
x += 10;
}
BUT...this seems like a horrible design. I wouldn't do this if I were personally writing from the ground up.

Dynamic button click event within a timer tick event

I have a grid with 9 buttons. In the timer tick event a random button is higlighted. If one clicks the higlighted button, a dynamic click event is created and within the click event the button is marked with a different color. The counterHits variable in the dynamic button click event is supposed to keep track of the highlighted buttons that were hit. Sometimes though it increases the variable more than by one. I cannot figure out why this is happening. Any help anyone?
public partial class Form1 : Form
{
const int buttons = 9;
int counterHits;
int counterTicks;
int currentIndex;
int lastIndex;
bool hit = false;
Random r;
Timer timerGameLoop;
Timer timerUpdateUI;
public Form1()
{
InitializeComponent();
timerGameLoop = new Timer();
timerGameLoop.Interval = 1000;
timerGameLoop.Tick += t_Tick;
timerUpdateUI = new Timer();
timerUpdateUI.Interval = 10;
timerUpdateUI.Tick += timerUpdateUI_Tick;
r = new Random();
}
// set up the grid and start
private void btnStart_Click(object sender, EventArgs e)
{
for (int i = 0; i < buttons; i++)
{
var b = new Button();
b.Size = new Size(100, 100);
b.Margin = new Padding(0);
b.BackColor = Color.White;
flowLayoutPanel.Controls.Add(b);
}
timerGameLoop.Start();
timerUpdateUI.Start();
}
// tick event ui update loop
void timerUpdateUI_Tick(object sender, EventArgs e)
{
lblHitCounter.Text = "hits : " + counterHits.ToString();
lblTickCounter.Text = "ticks : " + counterTicks.ToString();
}
// tick event game loop
void t_Tick(object sender, EventArgs e)
{
// reset to white background if not clicked
if (!hit)
flowLayoutPanel.Controls[lastIndex].BackColor = Color.White;
// highlight button to be clicked
currentIndex = r.Next(buttons);
lastIndex = currentIndex;
flowLayoutPanel.Controls[currentIndex].BackColor = Color.Violet;
// highligted button clicked
flowLayoutPanel.Controls[currentIndex].Click += b_Click;
hit = false;
counterTicks++;
}
// highlighted button clicked event
void b_Click(object sender, EventArgs e)
{
var b = (Button)sender;
b.BackColor = Color.Olive;
hit = true;
counterHits++;
b.Click -= b_Click;
}
}
The following lines attaches b_Click to your button. That eventhandler is only removed if you press the button
flowLayoutPanel.Controls[currentIndex].Click += b_Click;
See the implementation of b_Click
// highlighted button clicked event
void b_Click(object sender, EventArgs e)
{
//Stugg
b.Click -= b_Click;←Removed Here only if it is pressed
}
This line indicates that some buttons have more than one EventHandler attached. Therefore when you click the button eventhandler runs more than once.

Removing dynamically generated buttons

I'm working with C# windows forms and need some help. I have a button that creates other buttons and adds them to the list 'buttons'. I need to have each button created destroy itself when it is clicked.
//create new button
Button newButton = new Button();
newButton.Name = "aButt"+buttNum;
Debug.WriteLine(newButton.Name);
buttNum++;
newButton.Text = "Button!";
newButton.Height = 50;
newButton.Width = 50;
//controls where the new button gets placed
if (curX > 9)
{
curX = 0;
curY++;
//defines the point the button spawns
newButton.Location = new System.Drawing.Point((curX * 55)+10, curY * 55);
//increments X to avoid placing a button on top of another
curX++;
}
else
{
newButton.Location = new System.Drawing.Point((curX * 55) + 10, curY * 55);
curX++;
}
newButton.UseVisualStyleBackColor = true;
newButton.Click += new System.EventHandler(this.removeThisButton);
buttons.Add(newButton);
this.Controls.Add(newButton);
I have the event listener set up, but since the sender has no actual information on the button itself i'm not sure how to get rid of it.
Any help is appreciated!
The click event handler has the signature
private void myButton_Click(object sender, EventArgs e)
The object sender is the source of the event. Just cast that to a Button, and there's what got clicked:
Button whatWasClicked = sender as Button;
if(whatWasClicked == null)
// never mind -- it wasn't a button...
Sender is the button. You can remove it from Form's control collection like this:
private void removeThisButton(object sender, EventArgs e) {
this.Controls.Remove(sender);
}

Capture the right button click event

I'm playing around abit with winforms and its controls and just discovered how to do custommade buttonclicks. However, there is a problem. I've got a loop, that's looping through a list of elements, and if a condition appears - I'm creating a button that will pop up a gridview.
public void draw(ref Panel inputPanel) //draws the eventline
{
int stepCounter = 0;
for (int i = 0; i < DaysList.Count-1; i++)
{
Button b1;
if (DaysList[i].Elements.Count > max)
{
b1 = new Button(); //Create the box
b1.Width = 120;
b1.Height = 40; //Set width and height
b1.Location = new Point(stepCounter + 35, 70); //Location
inputPanel.Controls.Add(b1); //
b1.Text = "Check event date in grid";
b1.Show();
b1.BringToFront();
b1.Click += new EventHandler((sender, e) => btn_Click(sender, e, DaysList[i].Elements));
stepCounter += 200;
}
}
}
That was my method for creating the buttons and a click event for the when my condition appears. The function that is passed to the eventhandler looks like this:
public void btn_Click(object sender, EventArgs e, List<EventElement> inputElems)
{
Button button = sender as Button;
DataGridForm window = new DataGridForm(inputElems);
window.Show();
}
public class EventElement
{
public EventElement()
{
}
public int Count{get;set;}
public string Date{get;set;}
}
The clickpart of the event is fine but whenever i click the spawned buttons, I get the wrong data into the gridview. As an example: The loop has created four buttons for me and they are presented on a straight line on the form. But whenever i click one of the buttons - dosnt matter which one of them, the button always return the data of the last spawned button. A more clear example: lets say we have the list inputElems looks like this:
inputElems[0].Count -> 2644
inputElems[1].Count -> 2131
inputElems[2].Count -> 8467
inputElems[3].Count -> 5462
When i now click the second button, the input to the second buttons parameter list should have the values (sender, e, 2131), right? but for some reason, the last argument gets the same like the 4th element in the list, even though i call the secondly created button.
I figured that it has something to do with me always calling the last added button_click to the eventhandler of the button, if so, how do I call different clicks from the EventHandler?
Instead of passing inputElems with the EventHandler, you can use Tag.
E.g. use:
b1.Tag=i;
Then in your click event handler:
public void btn_Click(object sender, EventArgs e)
{
Button button = sender as Button;
DataGridForm window = new DataGridForm(DaysList[int.Parse(button.Tag.ToString())].Elements);
window.Show();
}
The problem is that the for loop is out of scope, and thus unable to provide you with the data you're looking for. A more straight forward approach might be something like this:
public void draw(ref Panel inputPanel) //draws the eventline
{
int stepCounter = 0;
for (int i = 0; i < DaysList.Count-1; i++)
{
Button b1;
if (DaysList[i].Elements.Count > max)
{
b1 = new Button(); //Create the box
b1.Width = 120;
b1.Height = 40; //Set width and height
b1.Location = new Point(stepCounter + 35, 70); //Location
inputPanel.Controls.Add(b1); //
b1.Text = "Check event date in grid";
b1.Show();
b1.BringToFront();
b1.Tag = DaysList[i].Elements;
b1.Click += btn_Click;
stepCounter += 200;
}
}
}
and then in btn_Click, do this:
public void btn_Click(object sender, EventArgs e)
{
Button button = sender as Button;
int inputElems = (List<EventElement>)button.Tag;
DataGridForm window = new DataGridForm(inputElems);
window.Show();
}

Categories