Dynamically Added LinkButtons Don't Fire OnClick Event - c#

I need paging on my web page. I use PagedDataSource for it. but I need pages to enumerated on the .aspx , So I add LinkButtons dynamically to PlaceHolder and Write one Eventhandler for all of them. It shows and works fine. on the first click Eventhandler is fired. on the second it doesn't fire. on the third it is. and so on... Any Idea?
protected void Page_Load(object sender, EventArgs e)
{
bindrepeater();
}
private void bindrepeater()
{
var service = new Service();
var coll = service.GetPeople();
PagedDataSource Pds1 = new PagedDataSource();
Pds1.DataSource = coll;
Pds1.AllowPaging = true;
Pds1.PageSize = 10;
Pds1.CurrentPageIndex = CurrentPage;
Repeater1.DataSource = Pds1;
Repeater1.DataBind();
var count = (coll.Count / 10) + 1;
pages.Controls.Clear();
for (int i = 1; i < count; i++)
{
var lb = new LinkButton() { Text = i.ToString(), CssClass = "hrefia" };
lb.Click += new EventHandler(lb_Click);
pages.Controls.Add(lb);
}
}
protected void lb_Click(object sender, EventArgs e)
{
var lb = (LinkButton)sender;
CurrentPage = int.Parse(lb.Text);
bindrepeater();
}
public int CurrentPage
{
get
{
object s1 = this.ViewState["CurrentPage"];
if (s1 == null)
{
return 0;
}
else
{
return Convert.ToInt32(s1);
}
}
set { this.ViewState["CurrentPage"] = value; }
}

It was needed to give ID to all of the linkbuttons.
#Hassan Boutougha ansered me in comments...
var lb = new LinkButton() { Text = i.ToString(), CssClass = "hrefia" };
lb = "btnId" + i.ToString();

One quick thing, on first load as per your code your current page index will be returned as 0.
Then on subsiquent page clicks like if you click on Page 2, the current page index returned will be 2, however if the page index starts with 0 then 2 means 3rd page rather than second page.
So i guess while setting the current page you should do as follows:
protected void lb_Click(object sender, EventArgs e)
{
var lb = (LinkButton)sender;
CurrentPage = int.Parse(lb.Text) **- 1**;
bindrepeater();
}

Related

Control Cache adding textboxes on auto post back

When the user selects the amount of textboxes require then that number of textboxes are populated. However, say the user selects 1 then goes back to change the amount to 2; then the amount of textboxes shown is 3. How do I stop it from adding when the page reloads.
protected List<Control> ControlCache
{
get { return (List<Control>)(Session["cachedControlsForPageX"] = (Session["cachedControlsForPageX"] as List<Control>) ?? new List<Control>()); }
set { Session["cachedControlsForPageX"] = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
foreach (var control in ControlCache)
{
ContentPlaceHolder1.Controls.Add(control);
ContentPlaceHolder1.Controls.Add(new LiteralControl(" "));
}
}
else
ControlCache = null;
}
protected void ddlCount_SelectedIndexChanged(object sender, EventArgs e)
{
int count = Convert.ToInt32(ddlCount.SelectedItem.Value);
for (int i = 0; i < count; i++)
{
TextBox tx = new TextBox();
tx.MaxLength = 10;
ContentPlaceHolder1.Controls.Add(tx);
ContentPlaceHolder1.Controls.Add(new LiteralControl(" "));
ControlCache.Add(tx);
}
}

Retrieving values from dynamically created controls Label in asp .net

I have created Label controls dynamically on button click:
protected void createDynamicLabels_Click(object sender, EventArgs e)
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label MyLabel = new Label();
MyLabel.ID = "lb" + i.ToString();
MyLabel.Text = "Labell: " + i.ToString();
MyLabel.Style["Clear"] = "Both";
MyLabel.Style["Float"] = "Left";
MyLabel.Style["margin-left"] = "100px";
Panel1.Controls.Add(MyLabel);
}
}
When I tried to read back fro another button I see Label Control returned null
Label str = (Label)Panel1.FindControl("lb" + i.ToString());
not sure what went wrong here
protected void bReadDynValue_Click(object sender, EventArgs e)
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label str = (Label)Panel1.FindControl("lb" + i.ToString());
lbGetText.Text = str.Text;
}
}
this is the issue of every time page load event. ASP.net fire every time page load event when any button is click.
suppose in this example..
protected void Page_Load(object sender, EventArgs e)
{
if(!IsPostBack)
createDynamicLabels();
}
private void createDynamicLabels()
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label MyLabel = new Label();
MyLabel.ID = "lb" + i.ToString();
MyLabel.Text = "Labell: " + i.ToString();
MyLabel.Style["Clear"] = "Both";
MyLabel.Style["Float"] = "Left";
MyLabel.Style["margin-left"] = "100px";
Panel1.Controls.Add(MyLabel);
}
}
protected void bReadDynValue_Click(object sender, EventArgs e)
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label str = (Label)Panel1.FindControl("lb" + i.ToString());
lbGetText.Text = str.Text;
}
}
when Button trigger Page doesn't have any label because it is made on runtime. and Page doesn't find particular label. if you tried above code it is run properly.
protected void Page_Load(object sender, EventArgs e)
{
createDynamicLabels();
}
private void createDynamicLabels()
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label MyLabel = new Label();
MyLabel.ID = "lb" + i.ToString();
MyLabel.Text = "Labell: " + i.ToString();
MyLabel.Style["Clear"] = "Both";
MyLabel.Style["Float"] = "Left";
MyLabel.Style["margin-left"] = "100px";
Panel1.Controls.Add(MyLabel);
}
}
protected void bReadDynValue_Click(object sender, EventArgs e)
{
int n = 5;
for (int i = 0; i < n; i++)
{
Label str = (Label)Panel1.FindControl("lb" + i.ToString());
lbGetText.Text = str.Text;
}
}
in this Example code find label every time because every time it can make labels for this page.
Dynamically created labels exists only until the next postback occurs. When you click on another button to retrieve their values a postback occurs and values become null.
For saving labels state after postback you have to use some hidden field.
If the text / value of the labes does not change it is enough to generate them on every postback (as mck already mentioned). If you need to retrieve changes made on the client side, you should create the controls in the OnInit event instead of the PageLoad and use inputs / texboxes instead of labels.
Another option (which I would recommend) would be to use a asp:Repeater to generate the Labels.

get values from dynamically added textboxes asp.net c#

as suggested in the title i have in which i can insert how many textboxes i want to add to a placeholder. i can add the textboxes just fine the problem is i cant get the values inserted on those dynamically added textboxes. here's my code
the purpose of this piece of code is to whenever the textbox in which i can introduce the number of textboxes i want. it creates and adds them to the placeholder in my page.
public void txtExtra_TextChanged(object sender, EventArgs e)
{
for (a = 1; a <= int.Parse(txtExtra.Text); a++)
{
TextBox txt = new TextBox();
txt.ID = "txtquestion" + a;
pholder.Controls.Add(txt);
}
}
this is the code of the button that will submit and response.write the values inserted in all those textboxes.
protected void btnConfirm_Click(object sender, EventArgs e)
{
foreach (Control ctr in pholder.Controls)
{
if (ctr is TextBox)
{
string value = ((TextBox)ctr).Text;
Response.Write(value);
}
}
}
i've been searching online and i've been getting answers that this code is fine and it should work but it doesnt. if you guys see anything wrong or have any suggestion that can solve my problem i'd really appreciate it
You are almost there.
Problem
You need to reload those dynamically created textboxes on post back. Otherwise, they will become null, and you won't be able to find it.
In order to do that, you need to save those dynamically TextBoxes Ids in persistent location such as View State or Session State.
Screen Shot
ASPX
Number of TextBoxes: <asp:TextBox runat="server" ID="CounterTextBox"
OnTextChanged="CounterTextBox_TextChanged" AutoPostBack="True" /><br/>
<asp:PlaceHolder runat="server" ID="TextBoxPlaceHolder" /><br/>
<asp:Button runat="server" ID="ConfirmButton" Text="Confirm"
OnClick="ConfirmButton_Click" /><br/>
Result: <asp:Literal runat="server" ID="ResultLiteral"/>
Code Behind
private List<string> TextBoxIdCollection
{
get
{
var collection = ViewState["TextBoxIdCollection"] as List<string>;
return collection ?? new List<string>();
}
set { ViewState["TextBoxIdCollection"] = value; }
}
protected void Page_Load(object sender, EventArgs e)
{
foreach (string textboxId in TextBoxIdCollection)
{
var textbox = new TextBox {ID = textboxId};
TextBoxPlaceHolder.Controls.Add(textbox);
}
}
protected void CounterTextBox_TextChanged(object sender, EventArgs e)
{
var collection = new List<string>();
int total;
if (Int32.TryParse(CounterTextBox.Text, out total))
{
for (int i = 1; i <= total; i++)
{
var textbox = new TextBox { ID = "QuestionTextBox" + i };
// Collect this textbox id
collection.Add(textbox.ID);
TextBoxPlaceHolder.Controls.Add(textbox);
}
TextBoxIdCollection= collection;
}
}
protected void ConfirmButton_Click(object sender, EventArgs e)
{
foreach (Control ctr in TextBoxPlaceHolder.Controls)
{
if (ctr is TextBox)
{
string value = ((TextBox)ctr).Text;
ResultLiteral.Text += value;
}
}
}
You are actually creating textboxes with property Text set to default = ""; So you need set txt.Text property for example:
public void txtExtra_TextChanged(object sender, EventArgs e)
{
for (int a = 1; a <= int.Parse(txtExtra.Text); a++)
{
TextBox txt = new TextBox();
txt.ID = "txtquestion" + a;
txt.Text = "Some text"; // Set some text here
pholder.Controls.Add(txt);
}
}
EDIT:
After that you can store your values into the list:
private static List<string> values = new List<string>();
protected void btnConfirm_Click(object sender, EventArgs e)
{
foreach (Control ctr in pholder.Controls)
{
if (ctr is TextBox)
{
string value = ((TextBox)ctr).Text;
values.Add(value); // add values here
}
}
}
EDIT:
Here is your values:
EDIT:
For super mega better understanding:
Create one more textbox txtOutput then add button GetDataFromTextBoxesAndPutItBelow and create an event for that button `Click'. Event code:
protected void btnGetData_Click(object sender, EventArgs e)
{
for (int i = 0; i < values.Count; i++)
txtOutput.Text += "Value from txtquestion1: " + values[i] + " ";
}
Screenshot looks:
for (int i = 0; i < dataTable.Rows.Count; i++)
{
int comment_id = Convert.ToInt32(dataTable.Rows[i]["comment_id"]);
string created_by_name = dataTable.Rows[i]["created_by_name"].ToString();
string created_at = dataTable.Rows[i]["created_at"].ToString();
string comment = dataTable.Rows[i]["comment"].ToString();
HtmlGenericControl divComment = new HtmlGenericControl("div"); //This is root object of comment.Other objects like textbox,button,etc added into this object.
//divComment.Attributes.Add("class", "div_post_display");
divComment.Attributes.Add("id", comment_id.ToString());
/* Comment by */
HtmlGenericControl lblCommentBy = new HtmlGenericControl("label");
//lblCommentBy.Attributes.Add("class", "divauthor");
lblCommentBy.InnerText = "" + created_by_name + " (" + created_at + ")";
/* Comment body */
HtmlGenericControl pComment = new HtmlGenericControl("p");
//lblCommentBy.Attributes.Add("class", "divauthor");
pComment.InnerText = comment;
divComment.Controls.Add(lblCommentBy);
divComment.Controls.Add(pComment);
if (Session["user_id"] != null)
{
if (Session["user_level"].ToString() == "1") //Admin can reply for comment
{
/* Reply Form */
TextBox txtReply = new TextBox(); //Create object dynamacaly
txtReply.ID = "txtReply_"+comment_id;
txtReply.Attributes.Add("class", "form-control"); //Add css class
txtReply.Width = 400;
divComment.Controls.Add(txtReply); //Add obj to root object(div)
Button btnReply = new Button(); //Create object dynamacaly
btnReply.Text = "Reply"; //Set button text
btnReply.Attributes.Add("class", "btn btn-sm btn-success"); //Add css class
btnReply.Click += btnReply_Click;
btnReply.CommandArgument = comment_id.ToString();
divComment.Controls.Add(btnReply); //Add obj to root object(div)
HtmlGenericControl br = new HtmlGenericControl("br"); //Create object dynamacaly
divComment.Controls.Add(br); //new line
}
}
pnlShowComments.Controls.Add(divComment);
}

Save Values of Dynamically created TextBoxes

guys i am creating dynamic TextBoxes everytime a button is clicked. but once i have as many text boxes as i want.. i want to save these value Database Table.. Please guide how to save it into DB
public void addmoreCustom_Click(object sender, EventArgs e)
{
if (ViewState["addmoreEdu"] != null)
{
myCount = (int)ViewState["addmoreEdu"];
}
myCount++;
ViewState["addmoreEdu"] = myCount;
//dynamicTextBoxes = new TextBox[myCount];
for (int i = 0; i < myCount; i++)
{
TextBox txtboxcustom = new TextBox();
Literal newlit = new Literal();
newlit.Text = "<br /><br />";
txtboxcustom.ID = "txtBoxcustom" + i.ToString();
myPlaceHolder.Controls.Add(txtboxcustom);
myPlaceHolder.Controls.Add(newlit);
dynamicTextBoxes = new TextBox[i];
}
}
You have to recreate the dynamical controls in Page_Load at the latest, otherwise the ViewState is not loaded correctly. You can however add a new dynamical control in an event handler(which happens after page_load in the page's lifefycle).
So addmoreCustom_Click is too late for the recreation of all already created controls, but it's not tool late to add a new control or to read the Text.
So something like this should work(untested):
public void Page_Load(object sender, EventArgs e)
{
if (ViewState["addmoreEdu"] != null)
{
myCount = (int)ViewState["addmoreEdu"];
}
addControls(myCount);
}
public void addmoreCustom_Click(object sender, EventArgs e)
{
if (ViewState["addmoreEdu"] != null)
{
myCount = (int)ViewState["addmoreEdu"];
}
myCount++;
ViewState["addmoreEdu"] = myCount;
addControls(1);
}
private void addControls(int count)
{
int txtCount = myPlaceHolder.Controls.OfType<TextBox>().Count();
for (int i = 0; i < count; i++)
{
TextBox txtboxcustom = new TextBox();
Literal newlit = new Literal();
newlit.Text = "<br /><br />";
txtboxcustom.ID = "txtBoxcustom" + txtCount.ToString();
myPlaceHolder.Controls.Add(txtboxcustom);
myPlaceHolder.Controls.Add(newlit);
}
}
Just enumerate the PlaceHolder-Controls to find your TextBoxes or use Linq:
private void saveData()
{
foreach (TextBox txt in myPlaceHolder.Controls.OfType<TextBox>())
{
string text = txt.Text;
// ...
}
}
Quick and dirty way would be to just iterate the Form collection looking for proper values:
if (Page.IsPostBack)
{
string name = "txtBoxcustom";
foreach (string key in Request.Form.Keys)
{
int index = key.IndexOf(name);
if (index >= 0)
{
int num = Int32.Parse(key.Substring(index + name.Length));
string value = Request.Form[key];
//store value of txtBoxcustom with that number to database...
}
}
}
To get values of dynamically created controls on postback you need to recreate those controls on Page_Init event
Then view state of those controls will be loaded and you will get controls and there values.
public void Page_Init(object sender, EventArgs e)
{
addControls(myCount);
}
I hope this will resolve your problem
Happy coding

ASP.NET dynamic controls count (creating controls as you go)

I'm trying to create a composite ASP.NET control that let's you build an editable control collection.
My problem is that when I press the add or postback button (which does nothing other than to postback the form) any values entered in the text boxes are lost.
I can't get it to work when the number of controls change between postbacks. I need to basically be able to recreate the control tree at two different times in the control life-cycle depending on the view state property ControlCount.
This test can be used to reproduce the issue:
public class AddManyControl : CompositeControl
{
protected override void OnLoad(EventArgs e)
{
base.OnLoad(e);
EnsureChildControls();
}
protected override void CreateChildControls()
{
var count = ViewState["ControlCount"] as int? ?? 0;
for (int i = 0; i < count; i++)
{
var div = new HtmlGenericControl("div");
var textBox = new TextBox();
textBox.ID = "tb" + i;
div.Controls.Add(textBox);
Controls.Add(div);
}
ViewState["ControlCount"] = count;
var btnAdd = new Button();
btnAdd.ID = "Add";
btnAdd.Text = "Add text box";
btnAdd.Click += new EventHandler(btnAdd_Click);
Controls.Add(btnAdd);
var btnPostBack = new Button();
btnPostBack.ID = "PostBack";
btnPostBack.Text = "Do PostBack";
Controls.Add(btnPostBack);
}
void btnAdd_Click(object sender, EventArgs e)
{
ViewState["ControlCount"] = (int)ViewState["ControlCount"] + 1;
}
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
// If I remove this RecreateChildControls call
// the collection lags behind each postback
// because the count is incremented in the btnAdd_Click event handler
// however, the values are not lost between postbacks
RecreateChildControls();
}
}
If you want to play with ASP.NET's custom controls, you have to play by its rule and its picky! When you start to play with the OnPreRender in a custom control, you know you're on the wrong track 90% of the time.
Generally, the best way to use the ViewState is to declare a property backed up by it, just like the standard ASP.NET controls do (.NET Reflector has been my teacher for years!). This way, it will be read and saved naturally during the event's lifecycle.
Here is a code that seems to do what you want, quite naturally, without any trick:
public class AddManyControl : CompositeControl
{
private void AddControl(int index)
{
var div = new HtmlGenericControl("div");
var textBox = new TextBox();
textBox.ID = "tb" + index;
div.Controls.Add(textBox);
Controls.AddAt(index, div);
}
protected override void CreateChildControls()
{
for (int i = 0; i < ControlsCount; i++)
{
AddControl(i);
}
var btnAdd = new Button();
btnAdd.ID = "Add";
btnAdd.Text = "Add text box";
btnAdd.Click += new EventHandler(btnAdd_Click);
Controls.Add(btnAdd);
var btnPostBack = new Button();
btnPostBack.ID = "PostBack";
btnPostBack.Text = "Do PostBack";
Controls.Add(btnPostBack);
}
private int ControlsCount
{
get
{
object o = ViewState["ControlCount"];
if (o != null)
return (int)o;
return 0;
}
set
{
ViewState["ControlCount"] = value;
}
}
void btnAdd_Click(object sender, EventArgs e)
{
int count = ControlsCount;
AddControl(count);
ControlsCount = count + 1;
}
}
I believe you have to add the control into the view state.

Categories