I have created 5 text boxes in a button click event and i have to get the values in the text boxes when the dynamically generated button is clicked.
protected void Button1_Click(object sender, EventArgs e)
{
for(int i=0;i<5;i++)
{
HtmlGenericControl tr = new HtmlGenericControl("tr");
HtmlGenericControl td = new HtmlGenericControl("td");
HtmlGenericControl tdbtn = new HtmlGenericControl("td");
TextBox txt=new TextBox();
txt.ID="txt_"+i.ToString();
td.Controls.Add(txt);
Button btn=new Button();
btn.ID="btn_"+i.ToString();
btn.Click+=new EventHandler(btnpay_Click);
btn.Text="Pay";
tdbtn.Controls.Add(btn);
tr.Controls.Add(td);
tr.Controls.Add(tdbtn);
PlaceHolder1.Controls.Add(tr);
}
}
But i couldn't get the Values in the text boxes at btnpay_Click
protected void btnpay_Click(object sender, EventArgs e)
{
Button btn = new Button();
btn = sender as Button;
string[] splitvaues = btn.ID.Split('_');
string identity = splitvaues[1];
TextBox txt = new TextBox();
txt =PlaceHolder1.FindControl("txt_" + identity) as TextBox;
}
Can Anybody tell me a way to solve this problem?
Your problem is that FindControl doesn't recurse down the control tree. It only searches the controls directly in the ControlCollection of the container.
This method will find a control only if the control is directly
contained by the specified container; that is, the method does not
search throughout a hierarchy of controls within controls.
You need to write a recursive FindControl. Something like:
public static Control FindControlRecursive(this Control control, string id)
{
if (control == null || control.ID == id) return control;
foreach (var c in control.Controls)
{
var found = c.FindControlRecursive(id);
if (found != null) return found;
}
return null;
}
try this code.....
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
createcontrol();
}
}
private void createcontrol()
{
for (int i = 0; i < 5; i++)
{
HtmlGenericControl tr = new HtmlGenericControl("tr");
HtmlGenericControl td = new HtmlGenericControl("td");
HtmlGenericControl tdbtn = new HtmlGenericControl("td");
TextBox txt = new TextBox();
txt.ID = "txt_" + i.ToString();
td.Controls.Add(txt);
Button btn = new Button();
btn.ID = "btn_" + i.ToString();
btn.Click += new EventHandler(btnpay_Click);
btn.Text = "Pay";
tdbtn.Controls.Add(btn);
tr.Controls.Add(td);
tr.Controls.Add(tdbtn);
plh1.Controls.Add(tr);
}
}
protected void btnpay_Click(object sender, EventArgs e)
{
Button btn = new Button();
btn = sender as Button;
string[] splitvaues = btn.ID.Split('_');
string identity = splitvaues[1].ToString();
TextBox txt = new TextBox();
txt = plh1.FindControl("txt_" + identity) as TextBox;
string q = txt.Text;
}
protected void Button1_Click(object sender, EventArgs e)
{
createcontrol();
}
Related
I'm looking for a solution to open folders with dynamically created buttons. Since I'm new to coding the solution i found so far is a bit wonky. Because im using a Textbox to get an actual string value which I can use.
public string MainDirPath = #"C:\....";
public string DirPath { get; set; }
public class Person
{
public string Name { get; set; }
}
private void Btn2_Click(object sender, RoutedEventArgs e)
{
Button Btn;
Person pers;
TextBox tb;
StackPanel s;
List<string> lstDirs = new List<string>(Directory.GetDirectories(MainDirPath));
foreach (string Dir in lstDirs)
{
Btn = new Button();
pers = new Person();
tb = new TextBox();
s = new StackPanel();
pers.Name = Dir;
tb.Text = Dir;
Btn.Content = tb;
Btn.Height = 200;
Btn.Name = "Button_" + (++i).ToString();
Btn.Click += new RoutedEventHandler(Btn_Click);
tb.MouseDoubleClick += new MouseButtonEventHandler(Tb_DoubleClick);
s.Children.Add(Btn);
StkPnl_MG.Children.Add(s);
}
}
void Btn_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
}
void Tb_DoubleClick(object sender, RoutedEventArgs e)
{
TextBox tb = sender as TextBox;
DirPath = tb.Text;
lstBox.Items.Add(tb.Text);
}
I was using Google to find a better soulution, but I might not know the right therms to look for.
I have Dynamically generated panels on my Form, every panel has multiple controls including TextBoxes, ComboBoxes and Buttons. I want to catch their values on a "Save" Button which is not dynamically generated (its in the form). I'm getting the Values with this code:
private void GetPanelControls(object sender, EventArgs e)
{
Panel allpanels = sender as Panel;
panelname = ItemsIDSelected[panelnamecounter] + "p";
//"p" identifies Panel and there is a counter with a list
if (allpanels.Name == panelname)
{
foreach (Control item in allpanels.Controls)
{
if (item.Name == (ItemsIDSelected[panelcontrolcounter] + "t")) //"t" identifies TextBox
{
ItemsNameListforInsert.Add(item.Text);
panelcontrolcounter++; //Panel has multiple controls
}
panelnamecounter++; //There are multiple Panels
}
}
}
How can I call this event on my Button_Click Event??
Panel panelGroup = new System.Windows.Forms.Panel();
panelGroup.Click += new EventHandler(GetPanelControls);
This is how Im Generating Panels and its event.
you can try something like this
private void Button_Click(object sender, EventArgs e)
{
GetPanelControls(this, new EventArgs());
}
EDIT
What if we use a method for this without using panel click event, if you need you can call this method inside the panel click event
private void GetPanelControls()
{
foreach (Control formControl in this.Controls)
{
if (formControl is Panel)
{
string panelName = ItemsIDSelected[panelnamecounter] + "p";
if (formControl.Name == panelName)
{
foreach (Control item in formControl.Controls)
{
// Your Code
}
}
}
}
}
//Control create button
private void button1_Click(object sender, EventArgs e)
{
Panel pnl = new Panel();
pnl.Name = "pnltest";
pnl.Location = new Point(500, 200);
TextBox txt1 = new TextBox();
txt1.Name = "txttest";
txt1.Location = new Point(0 ,10);
pnl.Controls.Add(txt1);
ComboBox cmb = new ComboBox();
cmb.Location = new Point(0, 50);
cmb.Name = "cmbtest";
cmb.Items.Add("one");
cmb.Items.Add("two");
cmb.Items.Add("three");
pnl.Controls.Add(cmb);
Button btn = new Button();
btn.Name = "btntest";
btn.Text = "submit";
btn.Location = new Point(0, 75);
btn.Click += btn_Click;
pnl.Controls.Add(btn);
this.Controls.Add(pnl);
}
//control button click event
void btn_Click(object sender, EventArgs e)
{
foreach (Control frmcntrl in this.Controls)
{
if (frmcntrl is Panel)
{
if (frmcntrl.Name == "pnltest")
{
foreach (Control item in frmcntrl.Controls)
{
if (item is TextBox)
{
if (item.Name == "txttest")
{
MessageBox.Show(item.Text .ToString());
}
}
else if (item is ComboBox)
{
if (item.Name == "cmbtest")
{
MessageBox.Show(item.Text);
}
}
}
}
}
}
}
I am adding text boxes dynamically and trying to capture data entered in text box on button click. but what is happening is , though I entered the data in the text box, when I clicked the button, the page is getting loaded and the control is getting created again. As a result , I am loosing the data in the text box. Can you tell me how can I capture this data entered to the dynamically created text boxes.
My sample code is as follows:
protected void Page_Load(object sender, EventArgs e)
{
Table tblTextboxes = new Table();
for(int i=0;i<10;i++)
{
TableRow tr=new TableRow();
TableCell tc=new TableCell();
TextBox tb=new TextBox();
tb.ID=i.ToString();
tc.Controls.Add(tb);
tr.Cells.Add(tc);
TableCell tc1=new TableCell();
LinkButton lnk=new LinkButton();
lnk.ID=i.ToString()+tb.Text+"lnk";
lnk.Text = "Show";
lnk.Click+=new EventHandler(lnk_Click);
tc1.Controls.Add(lnk);
tr.Cells.Add(tc1);
tblTextboxes.Rows.Add(tr);
}
placeTest.Controls.Add(tblTextboxes);
}
void lnk_Click(object sender, EventArgs e)
{
LinkButton lnk=sender as LinkButton;
Label lbl=new Label();
lbl.Text="The text is"+lnk.ID;
placeTest.Controls.Add(lbl);
}
LinkButton ID is changed every time you enter text into TextBox and post back.
One thing you want to make sure when creating control dynamically is - you want to recreate them with same ID when post back.
Updated Solution (to retrieve text from TextBox)
protected void Page_Load(object sender, EventArgs e)
{
var tblTextboxes = new Table();
for (int i = 0; i < 10; i++)
{
var tr = new TableRow();
var tc = new TableCell();
var tb = new TextBox {ID = i.ToString()};
tc.Controls.Add(tb);
tr.Cells.Add(tc);
var tc1 = new TableCell();
// This is a fix for - lnk.ID=i.ToString()+tb.Text+"lnk";
var lnk = new LinkButton {ID = i + "lnk", Text = "Show"};
lnk.Click += lnk_Click;
tc1.Controls.Add(lnk);
tr.Cells.Add(tc1);
tblTextboxes.Rows.Add(tr);
}
placeTest.Controls.Add(tblTextboxes);
}
void lnk_Click(object sender, EventArgs e)
{
var lnk = sender as LinkButton;
var lbl = new Label();
lbl.Text = "LinkButton ID: " + lnk.ID;
// Get number value from string
string id = Regex.Replace(lnk.ID, #"[^\d]", "");
// Retrieves a TextBox control by ID
var control = FindControlRecursive(Page, id);
if (control != null)
{
var textbox = control as TextBox;
lbl.Text += "; TextBox Text: " + textbox.Text;
}
placeTest.Controls.Add(lbl);
}
public Control FindControlRecursive(Control root, string id)
{
if (root.ID == id)
return root;
return root.Controls.Cast<Control>()
.Select(c => FindControlRecursive(c, id))
.FirstOrDefault(c => c != null);
}
Based on the MSDN, I would recommend to use Page class's Init event. Look in to the title View State and Dynamically Added Controls for explanation. Also, I would recommend to add dynamic controls at the end of all existing controls. Create table first, and then add the text boxes.
I modified your code. It worked for me. I used VS 2012, .Net 4.5
protected void Page_Load(object sender, EventArgs e)
{
Response.Write(DateTime.Now.ToString());
}
protected void Page_Init(object sender, EventArgs e)
{
Table tblTextboxes = new Table();
for (int i = 0; i < 10; i++)
{
TableRow tr = new TableRow();
TableCell tc = new TableCell();
TextBox tb = new TextBox();
tb.ID = i.ToString();
tc.Controls.Add(tb);
tr.Cells.Add(tc);
//TableCell tc1 = new TableCell();
//LinkButton lnk = new LinkButton();
//lnk.ID = i.ToString() + tb.Text + "lnk";
//lnk.Text = "Show";
//lnk.Click += new EventHandler(lnk_Click);
//tc1.Controls.Add(lnk);
//tr.Cells.Add(tc1);
tblTextboxes.Rows.Add(tr);
}
placeTest.Controls.Add(tblTextboxes);
}
protected void Button1_Click(object sender, EventArgs e)
{
}
Hi I am dynamically creating link buttons in a 'ul li' list. I am then trying to tie each link button to a click event where i set a label to the text of the link button clicked. however the event that should fire doesnt get fired?
if (!Page.IsPostBack)
{
int listItemIds = 0;
foreach (Node productcolour in product.Children)
{
HtmlGenericControl li = new HtmlGenericControl("li");
LinkButton lnk = new LinkButton();
lnk.ID = "lnk" + listItemIds;
lnk.Text = productcolour.Name;
lnk.Click += new EventHandler(Clicked);
//lnk.Command += new CommandEventHandler(lnkColourAlternative_Click);
//lnk.Click
li.Controls.Add(lnk);
ul1.Controls.Add(li);
listItemIds++;
}
}
the above is wrapped within a if(!page.ispostback) and the label text is never set anywhere else.
heres to the event
protected void Clicked(object sender, EventArgs e)
{
LinkButton lno = sender as LinkButton;
litSelectedColour.Text = lno.Text;
}
Code must run on each postback:
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
int listItemIds = 1;
for (int i = 0; i < 10; i++)
{
var li = new HtmlGenericControl("li");
var lnk = new LinkButton();
lnk.ID = "lnk" + listItemIds;
lnk.Text = "text" + i;
lnk.Click += Clicked;
//lnk.Command += new CommandEventHandler(lnkColourAlternative_Click);
//lnk.Click
li.Controls.Add(lnk);
ul1.Controls.Add(li);
listItemIds++;
}
}
private void Clicked(object sender, EventArgs e)
{
var btn = sender as LinkButton;
btn.Text = "Clicked";
}
Do this sort of thing OnInit and make sure you recreate the controls on every postback.
See this KB article for an example - a bit outdated but the methodology is still the same.
I am creating a TextBox and a Button dynamically using the following code:
Button btnClickMe = new Button();
btnClickMe.Content = "Click Me";
btnClickMe.Name = "btnClickMe";
btnClickMe.Click += new RoutedEventHandler(this.CallMeClick);
someStackPanel.Childern.Add(btnClickMe);
TextBox txtNumber = new TextBox();
txtNumber.Name = "txtNumber";
txtNumber.Text = "1776";
someStackPanel.Childern.Add(txtNumber);
I hook up to a click event to the Click Me button. The click me button even is fired correctly. However I cannot find the TextBox I entered dynamically.
Here is my click me event:
protected void ClickMeClick(object sender, RoutedEventArgs e)
{
// Find the phone number
TextBox txtNumber = this.someStackPanel.FindName("txtNumber") as TextBox;
if (txtNumber != null)
{
string message = string.Format("The number is {0}", txtNumber.Text);
MessageBox.Show(message);
}
else
{
MessageBox.Show("Textbox is null");
}
}
How can I find the TextBox txtNumber?
Josh G had the clue that fixed this code: use RegisterName().
Three benefits here:
Doesn't use a member variable to save the reference to the dynamically created TextBox.
Compiles.
Complete code.
using System;
using System.Windows;
using System.Windows.Controls;
namespace AddControlsDynamically
{
public partial class Window1 : Window
{
public void Window_Loaded(object sender, RoutedEventArgs e)
{
GenerateControls();
}
public void GenerateControls()
{
Button btnClickMe = new Button();
btnClickMe.Content = "Click Me";
btnClickMe.Name = "btnClickMe";
btnClickMe.Click += new RoutedEventHandler(this.CallMeClick);
someStackPanel.Children.Add(btnClickMe);
TextBox txtNumber = new TextBox();
txtNumber.Name = "txtNumber";
txtNumber.Text = "1776";
someStackPanel.Children.Add(txtNumber);
someStackPanel.RegisterName(txtNumber.Name, txtNumber);
}
protected void CallMeClick(object sender, RoutedEventArgs e)
{
TextBox txtNumber = (TextBox) this.someStackPanel.FindName("txtNumber");
string message = string.Format("The number is {0}", txtNumber.Text);
MessageBox.Show(message);
}
}
}
Another method is to set the associated TextBox as Button Tag when instanciating them.
btnClickMe.Tag = txtNumber;
This way you can retrieve it back in event handler.
protected void ClickMeClick(object sender, RoutedEventArgs e)
{
Button btnClickMe = sender as Button;
if (btnClickMe != null)
{
TextBox txtNumber = btnClickMe.Tag as TextBox;
// ...
}
}
You can get your original click handler to work by registering the name of the text box:
someStackPanel.RegisterName(txtNumber.Name, txtNumber);
This will then allow you to call FindName on the StackPanel and find the TextBox.
If you want to do a comprehensive search through the visual tree of controls, you can use the VisualTreeHelper class.
Use the following code to iterate through all of the visual children of a control:
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parentObj); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
if (child is TextBox)
// Do something
}
If you want to search down into the tree, you will want to perform this loop recursively, like so:
public delegate void TextBoxOperation(TextBox box);
public bool SearchChildren(DependencyObject parent, TextBoxOperation op)
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(parent, i);
TextBox box = child as TextBox;
if (box != null)
{
op.Invoke(box);
return true;
}
bool found = SearchChildren(child, op);
if (found)
return true;
}
}
Is there any way you can make the TextBox control a field in your class instead of a variable inside your generator method
public class MyWindow : Window
{
private TextBox txtNumber;
public void Window_Loaded()
{
GenerateControls();
}
public void GenerateControls()
{
Button btnClickMe = new Button();
btnClickMe.Content = "Click Me";
btnClickMe.Name = "btnClickMe";
btnClickMe.Click += new RoutedEventHandler(this.CallMeClick);
someStackPanel.Childern.Add(btnClickMe);
txtNumber = new TextBox();
txtNumber.Name = "txtNumber";
txtNumber.Text = "1776";
someStackPanel.Childern.Add(txtNumber);
}
protected void ClickMeClick(object sender, RoutedEventArgs e)
{
// Find the phone number
string message = string.Format("The number is {0}", txtNumber.Text);
MessageBox.Show(message);
}
}