Dynamic button, textbox and picturebox creation - c#

Here I am doing a project where questions are presented in images. When the project loads, "start exam" button will be present in the screen. After pressing the button, it should create a picturebox, a textbox and a button for each image from specified path. Then users has to enter the answer in a textbox which is created dynamically. After the dynamic submit button is clicked for every image, the textbox values have to be stored in the listbox. I don't know how get the values from textbox. Can anyone help me out from this?
Here is my code:
PictureBox[] pics = new PictureBox[100];
TextBox[] txts = new TextBox[100];
Button[] butns = new Button[100];
FlowLayoutPanel[] flws = new FlowLayoutPanel[100];
private void button1_Click( Object sender , EventArgs e)
{
for (int i = 0; i < listBox1.Items.Count; i++)
{
flws[i] = new FlowLayoutPanel();
flws[i].Name = "flw" + i;
flws[i].Location = new Point(3,brh);
flws[i].Size = new Size(317,122);
flws[i].BackColor = Color.DarkCyan;
flws[i].BorderStyle = BorderStyle.Fixed3D;
pics[i] = new PictureBox();
pics[i].Location = new Point(953, 95 + brh);
pics[i].Name = "pic" + i;
pics[i].Size = new Size(300, 75);
pics[i].ImageLocation = "C:/" + listBox1.Items[i];
flws[i].Controls.Add(pics[i]);
txts[i] = new TextBox();
txts[i].Name = "txt" + i;
txts[i].Location = new Point(953, 186 + brh);
flws[i].Controls.Add(txts[i]);
butns[i] = new Button();
butns[i].Click += new EventHandler(butns_Click);
butns[i].Text = "submit";
butns[i].Name = "but" + i;
butns[i].Location = new Point(1100, 186 + brh);
flws[i].Controls.Add(butns[i]);
flowLayoutPanel1.Controls.Add(flws[i]);
brh += 130;
}
}
private void butns_Click(object sender, EventArgs e)
{
Button butns = sender as Button;
TextBox txts = sender as TextBox;
listBox2.Items.Add("text values " + txts.Text.ToString());
}

I would create a usercontrol to combine the controls.
Search for "custom usercontrol c#"
Regards.

Try this...
private void butns_Click(object sender, EventArgs e)
{
Button butns = sender as Button;
string btnName = butns.Name;
string Id = btnName.Substring(3);
string txtName = "txt" + Id;
listBox2.Items.Add("text values " + GetValue(txtName));
}
private string GetValue(string name)
{
TextBox txt = new TextBox();
txt.Name = name;
foreach (Control ctl in this.Controls)
{
if (ctl is FlowLayoutPanel)
{
foreach (Control i in ctl.Controls)
{
if (((TextBox)i).Name == txt.Name)
{
txt = (TextBox)i;
return txt.Text;
}
}
}
}
return txt.Text;
}

Related

Check which Radio Button is checked in C#, with dynamically created radiobuttons

I can't find any solution or hint on this problem. Problem described after this code.
I must create one picturebox and radiobutton for every folder found on a specific path:
{
InitializeComponent();
string pathtocircuits = "../../tracks";
string[] allfiles = Directory.GetDirectories(pathtocircuits, "*.*", SearchOption.TopDirectoryOnly);
int imgx = 387;
int imgy = 153;
int radx = 428;
int rady = 259;
String track = "";
String pici = "";
String pic = "pictureBox";
String rad = "radiobutton";
String radr = "";
String picr = "";
foreach (String file in allfiles)
{
track = Path.GetFileName(file);
pici = "../../tracks/" + track + "/p_" + track + ".png";
picr = pic + element.ToString();
radr = rad + element.ToString();
PictureBox pb = new PictureBox();
pb.Location = new System.Drawing.Point(imgx, imgy); ;
pb.Image = Image.FromFile(pici);
pb.Width = 100;
pb.Height = 100;
pb.SizeMode = PictureBoxSizeMode.StretchImage;
pb.Name = picr;
Controls.Add(pb);
RadioButton rdo = new RadioButton();
rdo.Name = radr;
rdo.Text = "";
rdo.Tag = track;
rdo.Location = new Point(radx, rady);
this.Controls.Add(rdo);
element += 1;
imgx += 110;
radx += 110;
}
}
With this part I get to create the elements I need (it works).
My problem is when I press a button to reach Form2. How can I check which radiobutton is selected and store its Tag value in a String?
for(int i = 0; i<element; i++)
{
if( ??? .Checked == true )
{
globalstring = ??? .Tag;
}
}
If I try to use the name of a created radiobutton instead of a ??? it gives me an error like 'element ??? does not have a Checked or Tag attribute'
Add method below
Add to For loop : rdo.CheckedChanged += new EventHandler(radioButton_CheckedChanged);
private void radioButton_CheckedChanged(object sender, EventArgs e)
{
RadioButton button = sender as RadioButton;
string name = button.Text;
}
RadioButtons as any other control are stored in the Controls collection of their container. If you add them directly to the form you can retrieve them using this code.
protected void Button1_Click(object sender, EventArgs e)
{
var radio = this.Controls.OfType<RadioButton>().FirstOrDefault(x => x.Checked);
if(radio != null)
{
string tag = radio.Tag.ToString();
.....
// Form2 = new Form2(tag);
}
}
The radiobuttons are added to a same group by default, so you can get the checked radiobutton as followed.
List<RadioButton> radioButtons = this.Controls.OfType<RadioButton>().ToList();
RadioButton rb = radioButtons
.Where(r => r.Checked)
.Single();
string tag = rb.Tag.ToString();

asp.net c# event handler not working second time

I have an asp.net web page that contain panel that will filled up on run time
protected void Page_Load(object sender, EventArgs e)
{
buildStructure(1);
}
and this is the method
public void buildStructure(int level_id)
{
pMain.Controls.Clear();
//Response.Write(#"<script language='javascript'>alert('" + level_id + "');</script>");
DataUtility DU = new DataUtility(#"****");
DataTable dt = DU.GetDataTable("SELECT * FROM dbo.PRStructure_Main WHERE level_id = "+level_id);
int curr_level = 1;
int curr_child = 1;
int totalchild = 0;
if (dt.Rows.Count > 0)
{
Panel pLevel = new Panel();
pLevel.CssClass = "level";
Panel pItem = new Panel();
pItem.CssClass = "item-ceo";
Label lItem = new Label();
lItem.Text = dt.Rows[0].ItemArray[2].ToString();
pItem.Controls.Add(lItem);
pLevel.Controls.Add(pItem);
pMain.Controls.Add(pLevel);
Panel pLevelLine = new Panel();
pLevelLine.CssClass = "level";
Panel pItemLine = new Panel();
pItemLine.CssClass = "item-line-ceo";
Panel pLine = new Panel();
pLine.CssClass = "horizontal-line";
pItemLine.Controls.Add(pLine);
pLevelLine.Controls.Add(pItemLine);
pMain.Controls.Add(pLevelLine);
Panel pLevelLine2 = new Panel();
pLevelLine2.CssClass = "level";
Panel pLevel2 = new Panel();
pLevel2.CssClass = "level";
dt = DU.GetDataTable("SELECT * FROM dbo.PRStructure_Main WHERE level_parent = "+(Convert.ToInt32( dt.Rows[0].ItemArray[0].ToString())));
lbItem2 = new LinkButton[dt.Rows.Count];
for (int i = 0; i < dt.Rows.Count; i++)
{
Panel pItemLine2 = new Panel();
Panel pLine2 = new Panel();
if (i == 0)
{
pItemLine2.CssClass = "item-line-level2-first";
pLine2.CssClass = "horizontal-line2-first";
}
else if (i == dt.Rows.Count - 1)
{
pItemLine2.CssClass = "item-line-level2-last";
pLine2.CssClass = "horizontal-line2-last";
}
else
{
pItemLine2.CssClass = "item-line-level2-middle";
pLine2.CssClass = "horizontal-line2-middle";
}
pItemLine2.Controls.Add(pLine2);
pLevelLine2.Controls.Add(pItemLine2);
Panel pItem2 = new Panel();
pItem2.CssClass = "item-level2";
Panel pItemContent2 = new Panel();
pItemContent2.CssClass = "item-level2-content";
lbItem2[i] = new LinkButton();
lbItem2[i].Text = dt.Rows[i].ItemArray[2].ToString();
int current_level1 = (int)dt.Rows[i].ItemArray[0];
//lbItem2.OnClientClick = "alert('" + current_level1 + "')";
//lbItem2.Click += new EventHandler((s,e) => evHandler(s,e, current_level1));
lbItem2[i].Click += new System.EventHandler(delegate(Object o, EventArgs a)
{
evHandler(o, a, current_level1);
});
pItemContent2.Controls.Add(lbItem2[i]);
//pLevel.Controls.Add(lbItem);
DataTable dt2 = DU.GetDataTable("SELECT * FROM dbo.PRStructure_Main WHERE level_parent = " + dt.Rows[i].ItemArray[0]);
Panel pMenuLevel = new Panel();
pMenuLevel.CssClass = "menu-level2";
//<div class="menu-level2-items">Assets Integrity Management</div>
for (int j = 0; j < dt2.Rows.Count; j++)
{
Panel pMenuLevelItems = new Panel();
pMenuLevelItems.CssClass = "menu-level2-items";
LinkButton lbMenuItem = new LinkButton();
lbMenuItem.Text = dt2.Rows[j].ItemArray[2].ToString();
int current_level2 = (int)dt2.Rows[j].ItemArray[0];
//lbMenuItem.Click += new EventHandler(delegate (Object o, EventArgs ee) { evHandler(s, ee,current_level2)});
lbMenuItem.Click += new EventHandler(delegate (Object o, EventArgs a)
{
evHandler(o, a, current_level2);
});
pMenuLevelItems.Controls.Add(lbMenuItem);
DataTable dt3 = DU.GetDataTable("SELECT * FROM dbo.PRStructure_Main WHERE level_parent = " + dt2.Rows[j].ItemArray[0]);
Panel pSubMenuLevel = new Panel();
pSubMenuLevel.CssClass = "sub-menu-level2";
// <div class="sub-menu-level2-items"> Business Application Section </div>
for (int k = 0; k < dt3.Rows.Count; k++)
{
Panel pSubMenuLevelItems = new Panel();
pSubMenuLevelItems.CssClass = "menu-level2-items";
LinkButton lbSubMenuItem = new LinkButton();
lbSubMenuItem.Text = dt3.Rows[k].ItemArray[2].ToString();
int current_level3 = (int)dt3.Rows[k].ItemArray[0];
lbMenuItem.Click += new EventHandler((s, e) => evHandler(s, e, current_level3));
pSubMenuLevelItems.Controls.Add(lbSubMenuItem);
pSubMenuLevel.Controls.Add(pSubMenuLevelItems);
}
pMenuLevelItems.Controls.Add(pSubMenuLevel);
pMenuLevel.Controls.Add(pMenuLevelItems);
}
pItemContent2.Controls.Add(pMenuLevel);
pItem2.Controls.Add(pItemContent2);
pLevel2.Controls.Add(pItem2);
}
pMain.Controls.Add(pLevelLine2);
pMain.Controls.Add(pLevel2);
}
}
I have a problem in this section
lbMenuItem.Click += new EventHandler((s, e) => evHandler(s, e, current_level3));
and this is the handler method
public void evHandler(Object s,EventArgs e, int someData){
//Response.Write(#"<script language='javascript'>alert('" + someData + "');</script>");
ScriptManager.RegisterStartupScript(this.Page, this.Page.GetType(),"err_msg","alert('" + someData + "');",
true);
buildStructure(someData);
}
it work properly first time
but when i click it again its make page load.
I think your page_load should be like below
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack){
buildStructure(1);
}
}
You need to recreate the exact same controls when posting back. If the page loads with only one control how will it know to raise the click event for a control that doesn't exists.
Edit:
From what I understand about asp.net page life cycle, you must have the controls created before post back data is restored, that's how page control events fire. So if you have a control say LinkButtonA which was dynamically created on the page and you click on it, for the click event to trigger on the server during the post back, it must be recreated before post back data is restored, therefore try Recreating dynamic controls in Page_Init instead of Page_Load and try to keep the input to your method "buildStructure" the same. Say if you have called it from the event handler with buildStructure("fifth_level") make sure that Page_Init does the same buildStructure("fifth_level").
Microsoft recommends to create the dynamic controls on preint so you need to create the same controls on preinit like this
http://msdn.microsoft.com/en-us/library/ms178472.aspx
protected override void OnPreInit(EventArgs e)
{
}

change the Label text in runtime inside a panel

I am creating List of Panel. Each panel Contain a Label and Button . I have also a Button(button1). I want to change the label text of (panels[0]) when click button1. How can I do this.This is my c# code:
List<Panel> panels = new List<Panel>();
private void Panel()
{
var x = 0;
for (int i = 1; i < 5; i++)
{
x += 60;
var panel1 = new Panel() { Size = new Size(60, 140), Location = new Point(x, 100), BorderStyle = BorderStyle.FixedSingle };
panel1.Name = "pan" + i;
Label lbl = new Label();
lbl.Name = "lbl" + i;
lbl.Text = i.ToString();
lbl.Location = new Point(10, 20);
panel1.Controls.Add(lbl);
Button button = new Button();
button.Location = new Point(10, 90);
button.Size = new Size(40, 40);
button.Text = "Click";
panel1.Controls.Add(button);
panels.Add(panel1);
Controls.Add(panel1);
}
}
private void button1_Click(object sender, EventArgs e)
{
foreach (var p in panels)
{
}
}
Output:
But i want, When i Click button1 it will change Label text of zero index panels(I have pointed it using red mark).
Can anyone help me...
Ok, so you've got a button and a label within a panel. When you click a button of a panel, you wanna do something to the label in the same panel, right ?
So
private void BtnClick(object sender, EventArgs e) {
var button = (Button)sender;//you've got the button clicked
var panel = button.Parent;//you've got the panel.
//var label = panel.Controls.OfType<Label>().FirstOrDefault();//but don't think you get this in c# 3.0
var label = GetFirstLabel(panel);
if (label != null)
label.Text = "something";
}
private Label GetFirstLabel(Control parent) {
foreach (var control in parent.Controls) {
if (control is Label) return control as Label;
}
return null;
}
Usage
When you add your buttons, you can now do
Button button = new Button();
button.Location = new Point(10, 90);
button.Size = new Size(40, 40);
button.Text = "Click";
button.Click += BtnClick;
And this will work on all panels.
If you don't store reference to that Label then you can find it in controls of the first Panel by type for example:
panels[0].Controls.OfType<Label>().First().Text = "New Text";
or by name
panels[0].Controls.OfType<Label>().Single(l => l.Name == "lbl1").Text = "New Text";
you can do this with a simple method:
private void button1_Click(object sender, EventArgs e)
{
Label l = panels[0].Controls.Find("lbl1", false).FirstOrDefault() as Label;
l.Text = "TEXT";
}

Add label under button in a flowLayoutPanel

I need to dynamically create buttons with labels under them in a flowLayoutPanel when i drop a file onto the form. But how do I set the label position to be under the button since the FLP is arranging the controls by itself.. ?
What I've tried:
void Form1_DragDrop(object sender, DragEventArgs e)
{
string[] fileList = e.Data.GetData(DataFormats.FileDrop) as string[];
foreach (string s in fileList)
{
Button button = new Button();
button.Click += new EventHandler(this.button_Click);
fl_panel.Controls.Add(button);
Icon icon = System.Drawing.Icon.ExtractAssociatedIcon(filename);
Bitmap bmp = icon.ToBitmap();
button.BackgroundImage = bmp;
button.Width = 60;
button.Height = 75;
button.FlatStyle = FlatStyle.Flat;
button.BackgroundImageLayout = ImageLayout.Stretch;
int space = 5;
int Yy = button.Location.Y;
int Xx = button.Location.X;
Label label = new Label();
label.Location = new Point(Yy + space, Xx);
//label.Margin.Top = button.Margin.Bottom;
fl_panel.Controls.Add(label);
}
}
The best idea I know of is to implement a custom control that contains both a button and a label that are arranged correctly. Then add the custom control to the FlowLayoutPanel.
public class CustomControl:Control
{
private Button _button;
private Label _label;
public CustomControl(Button button, Label label)
{
_button = button;
_label = label;
Height = button.Height + label.Height;
Width = Math.Max(button.Width, label.Width);
Controls.Add(_button);
_button.Location = new Point(0,0);
Controls.Add(_label);
_label.Location = new Point(0, button.Height);
}
}
You can then add to it like this:
for (int i = 0; i < 10; i++)
{
CustomControl c = new CustomControl(new Button {Text = "Button!"}, new Label {Text = "Label!"});
fl_panel.Controls.Add(c);
}
EDIT:
If you want to listen to button events, try this:
for (int i = 0; i < 10; i++)
{
var button = new Button {Text = "Button " + i};
CustomControl c = new CustomControl(button, new Label {Text = "Label!"});
button.Click += buttonClicked;
fl_panel.Controls.Add(c);
}
...
private void buttonClicked(object sender, EventArgs e)
{
MessageBox.Show(((Button) sender).Text);
}

GUI output differs from local vs production

I am having a weird experience. I am dynamically creating a row of textboxes at runtime when the user clicks a button.
However, on my local machine the text boxes appear correctly (example
[TextBox1] [TextBox2] [TextBox3] [TextBox4] [TextBox5]
[TextBox1] [TextBox2] [TextBox3] [TextBox4] [TextBox5]
[TextBox1] [TextBox2] [TextBox3] [TextBox4] [TextBox5]
When I run this app on the production, the output side-by-side is:
[TextBox1][TextBox1] [TextBox2][TextBox2] [TextBox3][TextBox3] [TextBox4][TextBox4]
The output should be one row of textboxes, then a second row of 5 text boxes etc.
The code that builds the textboxes is:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
dyntxtCar = new TextBox[myCount];
dyntxtMake = new TextBox[myCount];
dyntxtMileage = new TextBox[myCount];
dyntxtVIN = new TextBox[myCount];
dyntxtSLIC = new TextBox[myCount];
dyntxtPlateNumber = new TextBox[myCount];
for (i = 0; i < myCount; i += 1)
{
TextBox txtCar = new TextBox();
TextBox txtMake = new TextBox();
TextBox txtMileage = new TextBox();
TextBox txtVIN = new TextBox();
TextBox txtSLIC = new TextBox();
TextBox txtPlateNumber = new TextBox();
txtCar.ID = "txtVehCar" + i.ToString();
txtMake.ID = "txtVehMake" + i.ToString();
txtMileage.ID = "txtVehMilage" + i.ToString();
txtVIN.ID = "txtVehVIN" + i.ToString();
txtSLIC.ID = "txtVehSLIC" + i.ToString();
txtPlateNumber.ID = "txtVehPlate" + i.ToString();
//Set tabIndex values for dynamic text fields;
txtCar.TabIndex = System.Convert.ToInt16(i * 10 + 1);
txtMake.TabIndex = System.Convert.ToInt16(i * 10 + 2);
txtMileage.TabIndex = System.Convert.ToInt16(i * 10 + 3);
txtVIN.TabIndex = System.Convert.ToInt16(i * 10 + 4);
txtSLIC.TabIndex = System.Convert.ToInt16(i * 10 + 5);
txtPlateNumber.TabIndex = System.Convert.ToInt16(i * 10 + 6);
//Set maxlength for dynamic fields;
txtCar.MaxLength = System.Convert.ToInt16(7);
txtVIN.MaxLength = System.Convert.ToInt16(17);
txtSLIC.MaxLength = System.Convert.ToInt16(4);
//Set width of text boxes
txtCar.Width = System.Convert.ToInt16("65");
txtMileage.Width = System.Convert.ToInt16("50");
txtVIN.Width = System.Convert.ToInt16("220");
txtSLIC.Width = System.Convert.ToInt16("45");
//txtPlateNumber.Width = System.Convert.ToInt16("35");
phCar.Controls.Add(txtCar);
phMake.Controls.Add(txtMake);
phMileage.Controls.Add(txtMileage);
phVIN.Controls.Add(txtVIN);
phSLIC.Controls.Add(txtSLIC);
phPlateNumber.Controls.Add(txtPlateNumber);
dyntxtCar[i] = txtCar;
dyntxtMake[i] = txtMake;
dyntxtMileage[i] = txtMileage;
dyntxtVIN[i] = txtVIN;
dyntxtSLIC[i] = txtSLIC;
dyntxtPlateNumber[i] = txtPlateNumber;
LiteralControl literalBreak = new LiteralControl("<br />");
phCar.Controls.Add(literalBreak);
phMake.Controls.Add(literalBreak);
phMileage.Controls.Add(literalBreak);
phVIN.Controls.Add(literalBreak);
phSLIC.Controls.Add(literalBreak);
phPlateNumber.Controls.Add(literalBreak);
}
}
protected void Page_PreInit(object sender, EventArgs e)
{
Control myControl = GetPostBackControl(this.Page);
if ((myControl != null))
{
if ((myControl.ClientID.ToString() == "btnAddTextBox"))
{
myCount = myCount + 1;
}
}
}
public static Control GetPostBackControl(Page thePage)
{
Control myControl = null;
string ctrlName = thePage.Request.Params.Get("__EVENTTARGET");
if (((ctrlName != null) & (ctrlName != string.Empty)))
{
myControl = thePage.FindControl(ctrlName);
}
else
{
foreach (string Item in thePage.Request.Form)
{
Control c = thePage.FindControl(Item);
if (((c) is System.Web.UI.WebControls.Button))
{
myControl = c;
}
}
}
return myControl;
}
Anyone experience this?

Categories