Creating a dynamic button - c#

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.

Related

How to access a certain button to change the value of a certain text field (in a dynamically created controls)

i need to use a button to make a number of textboxes with related buttons each button will add 1 to the textbox (that i want to be related to it HOW?)
i have a windows form with button1 and three panels
==========================================
using System;
using System.Drawing;
using System.Linq;
using System.Windows.Forms;
namespace AdvancedCounter
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
if (panel3.Controls != null)
{
var btn = panel3.Controls.Find("_B", true).First();
btn.Click += new EventHandler(Btn_Click);
}
}
int a = 0;
int counter=0;
private void button1_Click(object sender, EventArgs e)
{
counter++;
Button btn = new Button();
btn.Location = new Point(0, 100);
btn.Text = "ADD";
btn.Name ="_B";
btn.Dock = DockStyle.Left;
btn.Click += new EventHandler(Btn_Click);
TextBox txt = new TextBox();
txt.Name = "_T";
txt.Location = new Point(500, 100);
txt.Dock = DockStyle.Left;
txt.Text = a.ToString();
panel3.Controls.Add(txt);
panel3.Controls.Add(btn);
foreach (var item in panel3.Controls.Find("_B", true))
{
item.Text = "ass";
}
}
private void Btn_Click(object sender, EventArgs e)
{
// MessageBox.Show(sender.ToString());
// throw new NotImplementedException();
var txtbx= panel3.Controls.Find("_T", true).First();
var btnbx = panel3.Controls.Find("_B", true).First();
a++;
// find[1].Dispose();
txtbx.Text = a.ToString();
}
}
}
First you are giving same Name property for every TextBox and Button, you should not do that. Instead do like this for example:
btn.Name = "_B_"+ counter;
So you will have different Name for Buttons and TextBoxes. And in event handler:
private void Btn_Click(object sender, EventArgs e)
{
Button btn = sender as Button;
string index = btn.Name.Split('_')[2];
string tbName = "_T_" + index;
var txtbx= panel3.Controls.Find(tbName, true).First();
a++;
txtbx.Text = a.ToString();
}

How do I delete a a label/button based on its name? WPF Visual Studio 2015

I'm trying to delete a label and a button based on their name but unfortunately the option to remove them (that I know of) is through Children.Remove where it only accepts the actual label/button itself and not their name. I needed the name since it's the one that determines which X button belongs to who.
Label labels;
Button buttons;
int counter;
private void button_Copy_Click(object sender, RoutedEventArgs e)
{
counter++;
Label lbl = new Label();
lbl.Content = counter.ToString();
lbl.HorizontalAlignment = HorizontalAlignment.Center;
lbl.VerticalAlignment = VerticalAlignment.Center;
lbl.FontSize = 50;
lbl.Name = "lbl" + counter;
labels = lbl;
Button bt = new Button();
bt.Content = "X";
bt.HorizontalAlignment = HorizontalAlignment.Right;
bt.VerticalAlignment = VerticalAlignment.Top;
bt.Name = "btn" + counter;
buttons = bt;
bt.Click += Button_Click;
grid.Children.Add(lbl);
grid.Children.Add(bt);
}
private void Button_Click(object sender, EventArgs e)
{
grid.Children.Remove(labels.Name = "btn" + counter);
grid.Children.Remove(buttons);
}
The grid.Children.Remove(labels.Name = "btn" + counter); is not correct but hopefully it tells how I kinda wanted it to happen.
You can first get the child element using a LINQ Where expression:
var child = grid.Children.OfType<Control>().Where(x => x.Name == "btn" + counter).First();
And then call Remove:
grid.Children.Remove(child);

Button Click Frequency Array

I need to make a ListBox that displays how often a Button is clicked.
The user chooses how many buttons are available to click. Here is what I've tried:
int clicked;
clicked = int.Parse(((Button)(sender)).Text);
freq_array[clicked]++;
for (int i = 0; i < freq_array[clicked]; i++)
lstFrequencies.Items[clicked] = clicked + "\t\t" + freq_array[clicked];
freq_array uses the 'clicked' variable to add to the frequency that button has been clicked. Or, it's supposed to.
When I debug it, 'clicked' always comes out to 0. I want 'clicked' to equal the text value of the button that's clicked. When I try to run the program, I get an error saying "Input string was not in correct format."
Edit:
I was able to fix my program with help from you guys. I realized I didn't show enough of my code to be clear enough, and I apologize for that. I had to add some things and move things around and got it soon enough. Thank you all.
Here is the code just for those who may need help in the future:
public partial class Form1 : Form
{
int[] freq_array = new int[11];
int[] numList = new int[11];
int oBase = 0;
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
invisiblity();
}
private void invisiblity()
{
foreach (Control ctrl in this.Controls)
{
if (ctrl is Button)
if (Char.IsDigit(ctrl.Text[0]))
ctrl.Visible = false;
}
}
private void btnSetBase_Click(object sender, EventArgs e)
{
Form2 frmDialog = new Form2();
frmDialog.ShowDialog(this);
if (frmDialog.DialogResult == DialogResult.OK)
{
oBase = frmDialog.Base;
//lblOutDigits.Text = oBase.ToString();
for (int i = 0; i < oBase; i++)
{
numList[i] = i;
}
}
ShowBaseButtons(oBase);
}
private void ShowBaseButtons(int last_digit)
{
invisiblity();
foreach (Control ctrl in this.Controls)
{
if (ctrl is Button)
if (Char.IsDigit(ctrl.Text[0]))
if (int.Parse(ctrl.Text) <= last_digit - 1)
ctrl.Visible = true;
}
}
private void btnN_Click(object sender, EventArgs e)
{
lblOutDigits.Text += ((Button)(sender)).Text;
int clicked = int.Parse(((Button)(sender)).Text);
freq_array[clicked]++;
}
private void btnShowFreq_Click(object sender, EventArgs e)
{
lstFrequencies.Items.Clear();
for (int i = 0; i < oBase; i++)
lstFrequencies.Items.Add(numList[i] + " \t\t\t" + freq_array[i]);
}
Your code should work as long as your Button Text is actually just a number. Since what you are trying to do is create an index, what I usually do is use the Tag Property of the control, set it to the Index I want in the designer and then cast that to an Int.
i.e.
if (int.TryParse(((Button)sender).Tag.ToString(), out clicked))
freq_array[clicked]++;
I believe what is happening is that you are not initializing your ListBox, This example Code does work using your initial method. Just create a new Form and paste it in and test.
public partial class Form1 : Form
{
ListBox lstFrequencies = new ListBox();
int[] freq_array = new int[10];
public Form1()
{
InitializeComponent();
Size = new Size(400, 400);
lstFrequencies.Location = new Point(150, 0);
lstFrequencies.Size = new Size(150, 200);
Controls.Add(lstFrequencies);
int top = 0;
for (int i = 0; i < 10; i++)
{
Button btn = new Button();
btn.Size = new Size(70, 30);
btn.Location = new Point(5, top);
Controls.Add(btn);
top += 35;
btn.Tag = i;
btn.Text = i.ToString();
btn.Click += new EventHandler(btn_Click);
lstFrequencies.Items.Add(i.ToString());
}
}
void btn_Click(object sender, EventArgs e)
{
int clicked;
clicked = int.Parse(((Button)(sender)).Text);
freq_array[clicked]++;
lstFrequencies.Items[clicked] = clicked + "\t\t" + freq_array[clicked]; //Cleaned up you do not need to iterate your list
// Using my example code
//if (int.TryParse(((Button)sender).Tag.ToString(), out clicked))
//{
// freq_array[clicked]++;
// lstFrequencies.Items[clicked] = clicked + "\t\t" + freq_array[clicked];
//}
}
}
Your code always comes out to 0 because you never assign last clicked value to button text. Try this code:
int clicked = 0;
private void button1_Click(object sender, EventArgs e)
{
clicked = Convert.ToInt32(((Button)sender).Text);
lstFrequencies.Items.Add(((Button)sender).Name + " " + ++clicked);
button1.Text = clicked.ToString(); // you lose this line
}
EDIT: Counter from variable member
int clicked = 0;
private void button1_Click(object sender, EventArgs e)
{
// if you want to display button name, change .Text to .Name
lstFrequencies.Items.Add(((Button)sender).Text + " " + ++clicked);
}

Address a generated button for clickevent

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
}

Add Event at runtime

my method is :
private void button1_Click(object sender, EventArgs e)
{
for (int i = 1; i < 10; i++)
{
Button btn = new Button();
btn.Name = "btn" + i.ToString();
btn.Text = "btn" + i.ToString();
btn.Click += new EventHandler(this.btn_Click);
this.flowLayoutPanel1.Controls.Add(btn);
}
}
void btn_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
if (btn.Name == "btn1")
{
this.Text = "stack";
}
}
There is a better approach ?
The code you used:
btn.Click += new EventHandler(this.btn_Click);
Is the correct code to add the handler. Creating the buttons and adding them to their container looks good.
The only thing I would add is just make sure you are creating the controls on postback too, prior to viewstate being restored, so that the events can actually be called.
Or maybe:
private void button1_Click(object sender, EventArgs e)
{
for (int i = 1; i < 10; i++)
{
Button btn = new Button();
btn.Text = "btn" + i.ToString();
btn.Tag = i;
btn.Click += delegate
{
if ((int)btn.Tag == 1)
this.Text = "stack";
};
this.flowLayoutPanel1.Controls.Add(btn);
}
}

Categories