I want to create a lot of Labels and Buttons and to make this task easier and more dynamic I initialized these in a for loop in a pure C# Page (Page.cs).
How can I manipulate a specific Label with a Button_Clicked Event (in my case the Label with the index i, which has been created together with the Button in the for loop)?
Here is a summary of my problem:
// Constructor
public Page()
{
Label[] lb = new Label[10];
Button[] btn = new Button[lb.Length];
for (int i = 0; i < lb.Length; i++)
{
lb[i] = new Label();
btn[i] = new Button();
btn[i].Clicked += Button_Clicked;
// TODO Somehow reference the Label in the Button Clicked Method
}
// set Content ...
}
// Buton Clicked Method
private void Button_Clicked(object sender, EventArgs e)
{
lb[i].Text = "Hello World!";
// lb[i] should be the Label, which was initialized with the Button in the for loop
}
or is there a better way, to achieve my goal?
You may manipulate a specific Label with a Button_Clicked Event by wrapping a pair of button and label into one StackLayout and adding a ClassId property to each StackLayout.
The sample code is like this:
public partial class MainPage : ContentPage
{
Label[] lb;
Button[] btn;
StackLayout[] sl;
int i = 0;
public MainPage()
{
InitializeComponent();
sl = new StackLayout[10];
lb = new Label[10];
btn = new Button[lb.Length];
StackLayout content = new StackLayout();
for (i = 0; i < lb.Length; i++)
{
lb[i] = new Label()
{
Text = "Old Text"+i,
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.Center
};
btn[i] = new Button
{
Text = "Click to Change Label Text!"+i,
VerticalOptions = LayoutOptions.CenterAndExpand,
HorizontalOptions = LayoutOptions.Center,
};
btn[i].Clicked += (sender, e) => Button_Clicked(sender, e);
// TODO Somehow reference the Label in the Button Clicked Method
sl[i] = new StackLayout
{
ClassId = ""+i,
Children =
{
lb[i],
btn[i]
}
};
content.Children.Add(sl[i]);
}
Content = content;
}
// Buton Clicked Method
private void Button_Clicked(object sender, EventArgs e)
{
Button bt = sender as Button;
StackLayout layout = bt.Parent as StackLayout;
int index = Int32.Parse(layout.ClassId);
lb[index].Text = "Hello World!" + index;
}
}
The result is like this:
If you only have 10 labels, I would just use lambdas.
Label[] lb = new Label[10];
Button[] btn = new Button[lb.Length];
for (int i = 0; i < lb.Length; i++)
{
lb[i] = new Label();
btn[i] = new Button();
btn[i].Clicked += (s,e) => { lb[i].Text = "hello world" };
}
One of the ways to achieve this is to modify event handler during the registration.
for (int i = 0; i < lb.Length; i++)
{
lb[i] = new Label();
btn[i] = new Button();
btn[i].Clicked += (sender, e) => Button_Clicked(sender, e, i);
//Here i is to pass the index to event handler Button_Clicked;
}
And now, you could access index in button clicked event handler and you could access the label with the index passed.
Related
i have a List of Buttons ... but i want to make an events for each button in the list --i have tried this code
ButtonName.Click += (sender, args) =>
{
Point p = new Point(20 * j, 70);
Product[j].Location = p;
Product[j].Width = 200;
Product[j].Height = 250;
this.Controls.Add(Product[j]);
};
the event i want to make is that when click on any button it should show a List Box which is related to this button.
and every List box have its own data .... the only problem i want to get a solution for it is to make event for every button in list
is that possible ??
Update
for (int j = 0; j < Data.BTN_Name.Count; j++)
{
Category[j].Click += (sender, args) =>
{
Point p = new Point(20 * j, 70);
Product[j].Location = p;
Product[j].Width = 200;
Product[j].Height = 250;
this.Controls.Add(Product[j]);
};
It seems to me that you want to do this:
for (int j = 0; j < Data.BTN_Name.Count; j++)
{
Product[j] = new ListBox()
{
Location = new Point(20 * j, 70),
Width = 200,
Height = 250,
Visible = false,
};
this.Controls.Add(Product[j]);
var captured_j = j;
Category[j].Click += (s, ea) => Product[captured_j].Visible = true;
}
You must capture the j variable to use it in the event handler - hence the code var captured_j = j; just before the event handler.
As I can see, you are actualy trying to tie a some button to some listbox. As #TheGeneral said, you can use a Tag property of button, but I don't like this approach (although it has the right to be, it is just a matter of habit). Here is my example:
public class YourForm : Form
{
private IDictionary<Button, ListBox> _listboxes = new Dictionary<Button, ListBox>();
// use this if you create a button and listbox simultaneously
protected void CreateButtonAndList()
{
var listbox = new ListBox();
// initialize listbox as needed
var button = new Button();
// initialize button as needed
button.Click += ButtonClickHandler;
_listboxes.Add(button, listbox);
}
// use this if you create a button for already existing listbox
protected void CreateButtonFor(ListBox listbox)
{
var button = new Button();
// initialize button as needed
button.Click += ButtonClickHandler;
_listboxes.Add(button, listbox);
}
private void ButtonClickHandler(object sender, EventArgs e)
{
var listbox = _listboxes[sender];
// do what you want with listbox
}
}
Also note, that you probably doesn't need both CreateButtonAndList() and CreateButtonFor() methods. You may leave only one that fit your needs.
I am currently experimenting in WPF and just created a UniformGrid with 800 buttons which are created in a for loop. All buttons have their own names and share the same click event.
What I want to do now is the following: I want to click the first button (rect0) to change the color of this button and the next one (rect1).
I am totally stuck right now because everything I write into the click event refers to the button I clicked.
public MainWindow()
{
InitializeComponent();
for (int i = 0; i < 800; i++)
{
Button BTN_rect = new Button()
{
Name = "rect" + i,
Background = Brushes.White,
};
BTN_rect.Click += BTN_rect_Click;
Uniform.Children.Add(BTN_rect);
}
}
private void BTN_rect_Click(object sender, RoutedEventArgs e)
{
Button BTN_rect = sender as Button;
BTN_rect.Background = Brushes.Red;
MessageBox.Show(BTN_rect.Name);
}
There are a load of ways to do this.
I took a shortcut and put just 9 buttons in a stackpanel, otherwise the same.
public MainWindow()
{
InitializeComponent();
for (int i = 0; i < 8; i++)
{
Button BTN_rect = new Button()
{
Name = "rect" + i,
Content =Name,
Tag = i,
Background = Brushes.White,
};
BTN_rect.Click += BTN_rect_Click;
sp.Children.Add(BTN_rect);
}
}
private void BTN_rect_Click(object sender, RoutedEventArgs e)
{
Button current = sender as Button;
current.Background = Brushes.Red;
string targetName = $"rect{((int)current.Tag) + 1}";
Button nextButton = sp.Children.OfType<Button>().Where(x => x.Name == targetName).SingleOrDefault();
nextButton.Background = Brushes.Red;
}
Usually, you'd template data into repeated controls rather than add them in code, btw.
Label[] l1 = new Label[30];
DataTable dt = ConsoleApp2.CitiesDB.getCities(this.region);
foreach(DataRow row in dt.Rows)
{
count++;
string city = row.Field<string>("city");
l1[count] = new Label();
l1[count].Location = new System.Drawing.Point(x,y);
l1[count].Size = new Size(140, 80);
l1[count].Font = new System.Drawing.Font("Century Gothic", 8.5F);
l1[count].Text = city;
x = x + 260;
this.Controls.Add(l1[count]);
this.Refresh();
if(count == 4 || count %4 ==0)
{
y = y + 150;
x = 40;
}
//l1[count].Click += new EventHandler(l1_click);
}
So i made a dynamic labels (each label is a city name). how can i make each label clickable? i have a register form - what i want is if user clicks on "new york" then in the "city" textbox it will appear. the way with the EventHandler doesnt works for me);. what can i do?
what i mean in code that doesnt work:
protected void l1_click(object sender, EventArgs e)
{
RegisterForm register = new RegisterForm(username,email,password,address,phone);
register.state.Text = region;
register.city.Text = l1[count].Text;
register.Show();
}
thanks (:
Assign one click event for each label (dynamically created):
l1[count].Click += l1_click;
In the one click event use the sender argument to see which label was clicked on:
protected void l1_click(object sender, EventArgs e)
{
Label lbl = (Label)sender;
MessageBox.Show(lbl.Text);
}
I want to add buttons and textboxes dynamically on runtime with each
button react differently.
ie newbutton1 linked with texbox1 ,newbutton2linked withtextbox2`
Right now any button just prints from the first to the last textbox
one after the other.
Also consider that I have a button1 & textbox1 already on the form for guides
Here is my code :
List<Button> buttons = new List<Button>();
List<TextBox> textboxes = new List<TextBox>();
int NumTextBox = 0;
void click(object sender, EventArgs e)
{
MessageBox.Show(textboxes[NumTextBox].Text);
NumTextBox++;
}
int x = 0;
int y = 0;
void AddClick(object sender, EventArgs e)
{
Button newButton = new Button();
buttons.Add(newButton);
newButton.Click += click;//
// newButton.Location.Y = button1.Location.Y + 20;
newButton.Location = new Point(button1.Location.X, button1.Location.Y+25+x);
x += 25;
this.Controls.Add(newButton);
TextBox newTextBox = new TextBox();
textboxes.Add(newTextBox);
// newTextBox.Click += click;
newTextBox.Location = new Point(textBox1.Location.X, textBox1.Location.Y+25+y);
y += 25;
this.Controls.Add(newTextBox);
}
you can have a class like mybutton that inherits from button class, in this new class you can have a property with textbox type . just like following code . and in your code when you want to Instantiated Button you can use list<mybutton> and set linkedTextbox property with a textbox.
public class myButton:Button
{
...
public TextBox linkedTextBox{set;get;}
}
and in your code you should write some thing like this :
list<myButton> buttons=new list<myButton>();
Textbox someTextBox=new TextBox();
buttons[0].linkedTextbox=someTextBox;
and in your event you can use:
((myButton)sender).linkedTextBox.text="Some thing";
Thank you everyone , I followed #Franck's answer .So WHAT CHANGED :
I've deleted the pre-made button1 & textbox1 and add them
programatically on the Form_load so that I can add them in the
Lists
A proof screenshot : http://prntscr.com/aprqxz
CODE:
List<Button> buttons = new List<Button>();
List<TextBox> textboxes = new List<TextBox>();
Button button1 = new Button();
TextBox textBox1 = new TextBox();
int x = 0;
int y = 0;
void click(object sender, EventArgs e)
{
var txt = textboxes[Convert.ToInt32(((Button)sender).Tag)].Text;
MessageBox.Show(txt.ToString());
}
void AddClick(object sender, EventArgs e)
{
Button newButton = new Button();
newButton.Click += click;
newButton.Location = new Point(button1.Location.X, button1.Location.Y+25+x);
x += 25;
newButton.Tag = buttons.Count;
this.Controls.Add(newButton);
buttons.Add(newButton);
//
TextBox newTextBox = new TextBox();
newTextBox.Location = new Point(textBox1.Location.X, textBox1.Location.Y+25+y);
y += 25;
this.Controls.Add(newTextBox);
textboxes.Add(newTextBox);
}
void MainFormLoad(object sender, EventArgs e)
{
button1.Click += click;
button1.Location = new Point(55, 48);
button1.Tag = buttons.Count;
this.Controls.Add(button1);
buttons.Add(button1);
//
textBox1.Location = new Point(137, 50);
this.Controls.Add(textBox1);
textboxes.Add(textBox1);
}
EDIT 1: As the counting starts from 0 I didn't added newButton.Tag = buttons.count+1; I added just newButton.Tag = buttons.count;
I have added check boxes dynamically to a panel. now how can i get a alert message with "you have checked 1 or 2 or 3....". when check boxes get selected??
CheckBox[] premiumticket = new CheckBox[50];
private void Form1_Load(object sender, EventArgs e)
{
var panel1 = new Panel()
{
Size = new Size(600, 70),
Location = new Point(20, 130),
BorderStyle = BorderStyle.FixedSingle
};
for (int i = 0; i < 20; i++)
{
premiumticket[i]=new CheckBox();
premiumticket[i].Text=(i+1).ToString();
premiumticket[i].Name=(i+1).ToString();
premiumticket[i].Location=new Point(x,y);
panel1.Controls.Add(premiumticket[i]);
x = x - 55;
if (x < 55)
{
y = y + 20;
x = 550;
}
}
x = 550; y = 10;
Controls.Add(panel1);
}
Add an event-handler to each CheckBox:
public void Checkbox_CheckedChanged(Object sender, EventArgs e) {
CheckBox cb = (CheckBox)sender;
MessageBox.Show( cb.Name + " was clicked!");
}
for (int i = 0; i < 20; i++) {
premiumticket[i] = new CheckBox();
premiumticket[i].OnCheckChanged += new EventHandler( Checkbox_CheckedChange );
...
}
Dynamically Create events for Each Checkbox and put ur alert code on it
var checkBox = new CheckBox { ID = "WCCheckBox" + item.ItemID.ToString(), ItemID = item.ItemID, Checked = item.UserValue == "1", CssClass = "wounditem" };
Your implementation may be another.
Add this to your for loop:
premiumticket[i].OnCheckChanged += new EventHandler( premiumTicketChanged );
Checkbox toggled handler:
public void premiumTicketChanged (Object sender, EventArgs e)
{
int ticketCount = premiumticket.Count(c => c.Checked);
MessageBox.Show( string.Format("You have checked {0} checkboxes....", ticketCount));
}
After you add dynamically a control you can use AddHandler to manage the events of this control.
Remember set the checkbox autopostback property to true.