This web page create controls.
First control "Parent"
Second control "child". Child button creates by parent. But i have one problem, Page doesn't respond child event(((
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
namespace WebApplication14
{
public partial class WebForm1 : System.Web.UI.Page
{
private Button[] buttons = new Button[256];
protected void Page_Load(object sender, EventArgs e)
{
Maybe i have a problem with this section???
for (int i = 0; i < 10; i++) // Create 10 buttons
{
buttons[i] = new Button(); // New button
buttons[i].ID = "Button" + i; // Button id
buttons[i].Text = "Button " + i; // Button text
I don't know why this event not work propertly
buttons[i].Click += (c, cArgs) => //Set Event
{
TextBox1.Text += "Hi"; //Doesn't show me result.Why???
};
}
int val = 0;
Button b = new Button(); // Create new button
b.ID = "BT1"; // Set button id "BT1"
b.Text = "Click"; // Set on button text
form1.Controls.Add(b); // add this button to form1
b.Click += (k, kArgs) => // Give this button event with parameters
{
val = Convert.ToInt32(TextBox1.Text); // Convert value of TextBox1 to int32 and set this value to variable "val"
form1.Controls.Add(buttons[val]); // Add subButton by value seted on variable "Val"
};
}
}
}
I believe that it is best to have all UI objects and their events bound/added to the form at the beginning before the page is completely loaded (Page_Load), preferably at page initialization (Page_Init). Your current approach doesn’t bind the button's click event correctly because it’s happening after Page_Load after a click event occurs on button 'b'. To alleviate this, you should add ALL UI objects during Page_Init or if you must Page_Load BUT you can control their visibility instead. This way you can guarantee that all objects have their events bound to the form correctly:
C# Code-Behind:
protected void Page_Load(object sender, EventArgs e)
{
for (int i = 0; i < 10; i++) // Create 10 buttons
{
buttons[i] = new Button(); // New button
buttons[i].ID = "Button" + i; // Button id
buttons[i].Text = "Button " + i; // Button text
buttons[i].Click += (c, cArgs) => //Set Event
{
TextBox1.Text += "Hi";
};
buttons[i].Visible = false; // Set visibility to false
form1.Controls.Add(buttons[i]); // Add button to form1
}
int val = 0;
Button b = new Button(); // Create new button
b.ID = "BT1"; // Set button id "BT1"
b.Text = "Click"; // Set on button text
form1.Controls.Add(b); // add this button to form1
b.Click += (k, kArgs) => // Give this button event with parameters
{
val = Convert.ToInt32(TextBox1.Text); // Convert value of TextBox1 to int32 and set this value to variable "val"
buttons[val].Visible = true; // Set visibility to true
};
}
Related
I am trying to create some labels and buttons dynamically. I want to change the label's name on dynamically crated button click. When I am writing the button_click method, I can not access the label object directly. How can I do that?
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace DemoPanel
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
int lblYVal = 10;
int btnYVal = 50;
for(int i = 1; i< 5; i++)
{
Label lbl = new Label();
lbl.Text = "test";
lbl.Name = "test"+i.ToString();
lbl.Location = new System.Drawing.Point(10, lblYVal);
lbl.Visible = true;
Button btn = new Button();
btn.Text = "Click";
btn.Name = "textBtn" + i.ToString();
btn.Location = new System.Drawing.Point(10,btnYVal);
btn.Visible = true;
btn.Click += new EventHandler(this.btn_click);
this.Controls.Add(lbl);
this.Controls.Add(btn);
lblYVal += 70;
btnYVal += 70;
}
}
void btn_click(object sender, EventArgs e)
{
//How can i change label text from here.
//lbl.text //Does Not exist Error.
Label lbl = new Label();
lbl.Text = "New text"; //Not changing Label text
}
}
}
The for loop you've written knows about the button and the label. You can leverage this to write a click handler that captures the label. It's as simple as changing:
btn.Click += new EventHandler(this.btn_click);
To
btn.Click += (sender, args) => lbl.Text = "Clicked";
It doesn't have to be so short. You could, for example do:
btn.Click += (sender, args) => {
if(something > 0)
lbl.Text = "Did the process because something was > 0";
else
lbl.Text = "Can't start the process because something is 0";
}
Or if you have a method that "does stuff"
void DoTheProcessAndOutputToTheLabel(Label x){
int i = 0;
foreach(var thing in things){
bool success = ProcessTheThing(thing);
if(success)
i++;
}
x.Text = $"Processed {i} things";
}
btn.Click += (sender, args) => DoTheProcessAndOutputToTheLabel(lbl);
Not quite sure, in your comment you said "use the sender" but here this event handler only ever attaches to one button so you don't really need to do anything with the sender because it's obvious which sender is is. For example you might have:
btn.Tag = "hello"+i;
btn.Click += (sender, args) => DoTheProcessAndOutputToTheLabel(lbl, (sender as Control).Tag);
It will send the word "hello2" in as an argument (if it's the second go of the loop).. but realistically because you know the sender you could form anything:
var x = "hello"+i;
btn.Click += (sender, args) => DoTheProcessAndOutputToTheLabel(lbl, x);
I only foresee the sender but being useful if something else changes the UI between you setting up and the user clicking the button - for example if they run a process that alters the button Tag, then sure, use the sender to grab the latest value
You can maintain a dictionary of buttons to labels and use that to find the matching label. Another option would be to associate an index with both button and label and find the label with that.
I'll illustrate the dictionary option to you.
Dictionary<Button, Label> mapping = new Dictionary<Button, Label>();
...
In your loop,
mapping[btn] = lbl;
In your handler,
((Label)mapping[(Button)sender)]).Text = "some text";
I created a function that appends buttons in a form. Buttons when clicked supposed to open different files. File paths are in listbox1. I want to add a click event for every button I append. One button should open one file from listbox1.
The part with appending buttons works, but I can't add a different event for each of them only one.
This is my code. It adds the event to every button but only the last one.
PlaySong is a function that plays ".mp3" file. That works.
Can someone help me?
int i = 0;
private void Load_Songs()
{
List<string> url = new List<string>();
url = listBox1.Items.Cast<String>().ToList();
int p = 5;
for (int j = 0; j < listBox1.Items.Count; j++)
{
EventHandler klik = new EventHandler(Playing);
Song_Data titl = new Song_Data(url[j]);
Button n = new Button
{
Text = titl.Title,
Location = new Point(0, p + 20),
Width = ClientRectangle.Width / 3,
FlatStyle = FlatStyle.Flat
};
p += 20;
n.Click += klik;
List_Artist.Controls.Add(n);
i++;
}
}
private void Playing(object sender, EventArgs e)
{
PlaySong(listBox1.Items[i].ToString());
}
You don't need many event handlers, just store the index to the button's Tag in your loop and then use it to find which index you should use to choose from listbox:
Button n = new Button
{
Text = titl.Title,
Location = new Point(0, p + 20),
Width = ClientRectangle.Width / 3,
FlatStyle = FlatStyle.Flat,
Tag = j
};
Then in your handler:
private void Playing(object sender, EventArgs e)
{
int i= (int)((Button)sender).Tag;
PlaySong(listBox1.Items[i].ToString());
}
to use different handler for each button you can use anonymous event handler, but won't solve your problem:
n.Click += (s, ev) =>
{
//code when button clicked
};
I create buttons in my application by:
List<Button> btnslist = new List<Button>();
for (int i = 0; i < nbrofbtns; i++)
{
Button newButton = new Button();
btnslist.Add(newButton);
this.Controls.Add(newButton);
newButton.Width = btnsidelength;
newButton.Height = btnsidelength;
newButton.Top = btnsidelength
* Convert.ToInt32(Math.Floor(Convert.ToDouble(i / Form2.puzzlesize)));
newButton.Left = btnsidelength
* Convert.ToInt32(
Math.Floor(Convert.ToDouble(i))
- Math.Floor((Convert.ToDouble(i))
/ (Form2.puzzlesize)) * (Form2.puzzlesize));
newButton.BackgroundImage = Lights_out_.Properties.Resources.LightsOutBlack;
newButton.Tag = (i+1).ToString();
newButton.Click += new EventHandler(Any_Button_Click);
Then I have a method for when any of the buttons are clicked.
void Any_Button_Click(object sender, EventArgs e)
{
//the variable b has all the insformation that the single button had itself.
Button b = (Button)sender;
if (b.BackgroundImage == Lights_out_.Properties.Resources.LightsOutBlack)
{
MessageBox.Show(b.Tag.ToString());
MessageBox.Show(btnslist[Convert.ToInt32(b.Tag)].BackgroundImage.ToString());
btnslist[Convert.ToInt32(b.Tag)].BackgroundImage =
Lights_out_.Properties.Resources.LightsOutWhite;
MessageBox.Show(btnslist[Convert.ToInt32(b.Tag)].BackgroundImage.ToString());
}
else
{
MessageBox.Show("b.backgroundimage != lightsoutblack. Backgroundimage = "
+ b.BackgroundImage.ToString());
}
}
How do I change the data in the actual button (then said button is clicked)? I want specificly to change the backgroundimage. How could I do this?? (I also need to change the backgroundimage of some other buttons created by the code.)
The sender object is the button:
Button b = (Button)sender;
... so you should be able to change properties on it directly:
b.WhateverPropsToChange = yourSetting;
PS: I don't think this is necessary, but if the button is not updated directly, you might try to using b.Refresh() to let it know something has changed.
You're handling Click event of every button you've created - and sender in Any_Button_Click is actually the button was clicked.
So just change b.BackgroundImage to whatever you need.
What am doing here is; making a UI to update values visually, will add more support for other types too. Possibly all types.
updateIcons this function is called everytime the controller is loaded, and has new values,names everytime.
countControls to keep track of controllers, so if can update values on clicks.
myP is the object that holds the values taken at runtime, user shuffles values by pressing tab from another screen
created radiobuttons groupboxes to allow radiobutton group to be managed.
properties all belong to one object. each property has few possible values like in my example, the enums.
now am kinda lost, not sure how to best do this, as now my rb_CheckedChanged is returning some kind of mess.
How do i do this the right way ? all together, i feel its somewhat the right approach At least.
I thought of making a dictionary of ? to use it at the checked event. not exactly sure how
private void updateIcons(List<Props> prop) {
countControls++;
locationY = 10;
int gbHeight;
foreach (var p in prop) {
radioButtonY = 10;
IType pType = p.Type;
if (pType is Enum) {
var myP = new MyProp(p, this);
GroupBox gb = new GroupBox();
gb.Location = new Point(nextLocationX,locationY);
nextLocationX += rbWidth+10;
gb.Name = "groupBox" + countControls;
gb.Text = "smthn";
var TypesArray = set here;
gbHeight = TypesArray.Length;
foreach (var type in TypesArray) {
getimagesPath(TypesArray);
RadioButton rb = new RadioButton();
rb.Appearance = Appearance.Button;
rb.Width = rbWidth;
rb.Height = rbHeight;
rb.Name = type.Name + countControls;
rb.Text = type.Name;
string path = imagePaths[type.Name];
Bitmap rbImage = new Bitmap(path);
rb.BackgroundImage = rbImage;
countControls++;
rb.Location = new Point(radioButtonX, radioButtonY);
if (myP.Value != null && type.Name.SafeEquals(myP.Value.ToString())) {
rb.Checked = true;
}
radioButtonY += rbHeight;
gb.Controls.Add(rb);
rb.CheckedChanged += rb_CheckedChanged;
}
gb.Height = rbHeight * gbHeight + 20;
gb.Width = rbWidth + 10;
Controls.Add(gb);
}
}
}
void rb_CheckedChanged(object sender, EventArgs e) {
RadioButton rb = (RadioButton)sender;
Control control = (Control)sender;
if (rb.Checked) {
MessageBox.Show("You have just checked: " + rb.Text);
MessageBox.Show("You have just called Controller: " + control.Name);
var t = PropSeq;
}
else {
MessageBox.Show("you have just unchecked: " + rb.Text);
MessageBox.Show("You have just called Controller: " + control.Name);
}
}
I think your code might be a little messed up and not the easiest to read. It looks plain invalid with not all closing braces present? Try the code below which will create two group boxes, each with five radio buttons. This should help you achieve what you are trying to do (full listing for a basic Form):
using System;
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
CreateButton();
}
private void CreateButton()
{
// Add two group boxes
for (int groupCount = 1; groupCount < 3; groupCount++)
{
var groupBox = new GroupBox();
groupBox.Location = new Point(220 * (groupCount - 1), 10);
groupBox.Name = string.Format("groupBox{0}", groupCount);
groupBox.Text = string.Format("Group Box {0}", groupCount);
// Add some radio buttons to each
for (int buttonCount = 1; buttonCount < 6; buttonCount++)
{
var radioButton = new RadioButton();
radioButton.Width = 150;
radioButton.Location = new Point(10, 30 * buttonCount);
radioButton.Appearance = Appearance.Button;
radioButton.Name = string.Format("radioButton{0}", buttonCount);
radioButton.Text = string.Format("Dynamic Radio Button {0} - {1}", groupCount, buttonCount);
radioButton.CheckedChanged += radioButton_CheckedChanged;
// Add radio button to the group box
groupBox.Controls.Add(radioButton);
groupBox.Height += 20;
}
// Add group box to form
Controls.Add(groupBox);
}
}
private void radioButton_CheckedChanged(object sender, EventArgs e)
{
// Get button and only show the selected (not now de-selected item)
var radioButton = (RadioButton)sender;
if (radioButton.Checked)
{
MessageBox.Show("You have just checked: " + radioButton.Text);
}
}
}
}
I have associated a Button ID while generating Buttons dynamically and created a Button event handler as follows:
btn.Click += new EventHandler(btn_Click);
Button Click event:
protected void btn_Click(object sender,EventArgs e)
{
Button b = new Button();
b = (Button)sender;
string i = b.ID.Substring(b.ID.Length - 1, 1);
int j1 =Convert.ToInt32(i);
id1 = to[j1];
Page.ClientScript.RegisterClientScriptBlock(Type.GetType("System.String"),
"addScript", "PassValues('" + id1 + "')", true);
ScriptManager.RegisterStartupScript(this, this.GetType(),
"sendMessage", "javascript:sendMessage(); ", true);
}
However this event is not getting called i have placed all my controls inside an UpdatePanel
EDIT: What is happening is on button click somehow a function is getting called which is present on Page.Load
protected void getEntriesRight()
{
j = (int)Session["j"];
int n1 = j + 3;
for (; j <= n1; j++)
{
if (j < fr.data.Length)
{
HtmlGenericControl listItem = new HtmlGenericControl("li");
HtmlGenericControl a1 = new HtmlGenericControl("a");
Label anchor = new Label();
Image im = new Image();
btn = new Button();
im.ImageUrl = fr.data[j].pic_square;
im.Height = 45;
im.Width = 47;
btn.CssClass = "btn-add";
btn.Text = "Invite";
to[j] = fr.data[j].uid;
btn.ID = "btn" + j;
a1.Attributes.Add("href", "#");
anchor.Text = fr.data[j].name;
a1.Controls.Add(btn);
a1.Controls.Add(im);
a1.Controls.Add(anchor);
listItem.Controls.Add(a1);
list.Controls.Add(listItem);
btn.Click += new EventHandler(btn_Click);
}
}
Session["j"] = j;
}
Help!
Dynamically generated controls have to be recreated on every postback in order for their events to fire. This is one of the most commonly-encountered problems with generating controls programmatically in .NET, and it is discouraged if you can find a way around it.
For example, if you have a button that should only be present when another button is clicked, have the button in the page to begin with, and use the Visible property to control whether it is shown or not.
Regarding your edit. Every post-back to the server, even inside an UpdatePanel, is going to call Page_Load. If you want to detect whether a request has come from an UpdatePanel then you need to check !Page.IsAsync before calling the function.