Getting wrong sender in event handler for checkboxes - asp.net

I have dynamically generated checkboxes and having EventHandler which takes care about check change of any of the checkbox. The issue is that if i uncheck any of the checkbox, it gets all other checkbox as sender and checkchange is called according to number of checkboxes number of times. If there are 3 checkboxes and 1 is unchecked than checkchange event handler is called 2 times. I dont understand what is happening.
CheckBox chkbox;
panelDynamicCheckbox.Controls.Clear();
foreach(string product in products)
{
chkbox = new CheckBox();
chkbox.ID = product;
chkbox.Text = product;
chkbox.AutoPostBack = true;
chkbox.CheckedChanged += new EventHandler(this.CheckChanged);
panelDynamicCheckbox.Controls.Add(chkbox);
}
protected void CheckChanged(object sender, EventArgs e)
{
CheckBox checkbox = (CheckBox)sender;
}

Ensure the code to add the dynamic checkbox and especially the event handler specification is done in the OnInit method in the page life-cycle. If you don't do this, these sort of unpredictable state behavior can be seen.

Related

How can I add a new dynamic control on button click?

When I click btnGDynamicCont I want to load the first set of controls, then on each further click of that button, add a new control (textbox) alongside the other ones, so each time it is clicked I am adding a new textbox across state.
Do you know where I should add the creation of the new textbox in order to keep it after each postback?
{
protected void Page_Load(object sender, EventArgs e)
{
if (Convert.ToString(ViewState["Generated"]) == "true")
GenerateDynamicControls();
}
public void GenerateDynamicControls()
{
TextBox txtDynamic = new TextBox();
txtDynamic.ID = "txtDynamic";
txtDynamic.Text = "Dynamic TextBox";
Page.Form.Controls.Add(txtDynamic);
TextBox txtDynamic2 = new TextBox();
txtDynamic2.ID = "txtDynamic2";
txtDynamic2.Text = "Dynamic Textbox";
Page.Form.Controls.Add(txtDynamic2);
}
protected void btnGDynamicCont_Click1(object sender, EventArgs e)
{
if (Convert.ToString(ViewState["Generated"]) != "true")
{
GenerateDynamicControls();
ViewState["Generated"] = "true";
}
else
{
Response.Write("<h2>Controls are already exist in page</h2>");
}
}
}
}
Dynamic controls are usually recreated at the Page_Load method. For more information, please refer to the Dynamically Created Controls in ASP.NET article.
You can refer the below link where a very similar issue is addressed.
unable to add more than one server control dynamically in asp.net
Everytime a postback happens, you should recreate the already existing controls(dynamically added) in your page_load event and the new controls are to be created in the button_click event.
Use some logic to generate ids for the controls for the viewstate to be maintained. VIEWSTATE will be taken care automatically if the ids of the controls generated before and after postback are the same.
One way to keep track of the number of textboxes is to store the count in session.

How to know which dropdownlist onchange event was triggerd in asp.net?

Im trying to do a rather simple practice project and i got stuck for a while now.
I have 3 dropdownlists
and 3 views.
I want to do:
check if the current dropdownlist has chosen a value then that dropdown has a value, hide that view and show the next view.
my problem:
I have one method for all 3 of my dropdownlists that gets called when a change occurs.
I need to check which one of these dropdownlists triggerd the change so that i know which dropdownlist value i need to check(if it is empty or not) and depending on the value i show/hide views.
If more info is needed just ask and Thanks!
On the function you probably have something like
protected void OnChangedEvent(object sender, EventArgs e) {
// code here
}
sender contains the dropdown list that fired the event. So:
protected void OnChangedEvent(object sender, EventArgs e) {
var ddl = (DropDownList)sender;
}
and ddl will be the dropdown list.

ASP.NET: How to access a dynamically created control

I'm creating a bunch of Checkboxes dynamically:
CheckBox chkRead = new CheckBox();
chkRead.ID = "chk1";
chkRead.AutoPostBack = true;
chkRead.CheckedChanged += new EventHandler(CheckBox_CheckedChanged);
CheckBox chkPost = new CheckBox();
chkRead.ID = "chk2";
chkPost.AutoPostBack = true;
chkPost.CheckedChanged += new EventHandler(CheckBox_CheckedChanged);
protected void CheckBox_CheckedChanged(object sender, EventArgs e)
{
CheckBox chk = (CheckBox)sender;
}
What I want to do is the following:
When I check the chkPost CheckBox I want the chkRead CheckBox to be checked as well
In the CheckBox_CheckedChanged event I only have access to the CheckBox that was clicked
but I don't know how to check the other checkbox from that event.
This is from memory, but you could do something like this:
protected void CheckBox_CheckedChanged(object sender, EventArgs e)
{
CheckBox chk = (CheckBox)sender;
CheckBox chkPost = (CheckBox) chk.NamingContainer.FindControl("chk2");
CheckBox chkRead = (CheckBox) chk.NamingContainer.FindControl("chk1");
if(chk == chkPost && chk.Checked)
{
chkRead.Checked = true;
}
}
This is assuming you want to do all this in code-behind, after postback. If you want to do it in javascript, that's a different question.
This also assumes that chk1 and chk2 are in the same naming container. If they aren't, things will get complicated.
Since it is your code that creates the checkboxes, you can store their references in a list or dictionary and retrieve them by id when needed.
If you want to do it dynamically you can add an attribute to the checkboxess you are interested in-- you can then loop over the Page.Controls collection and test that the control you are looping over has that attribute and then you can check, or uncheck it.
some pseudo code:
foreach(var control in Page.Controls)
if(typeof(Control) is CheckBox and ((CheckBox)control).Attributes["myAttr"] != null)
//check or uncheck it
In reading your comment about nested controls-- this might be a bit of a hassle-- I tend to agree with Igor, that you should put the id's in a collection as they are being added dynamically.
Could you paste code where you are creating these checkboxes? Is it "OnInit" or somewhere else? Are you putting these checkboxes in container, do you store these controls as global variables or create them in method?

Checkbox checked state change when visibility is set to false

I am having some trouble understanding the impact of setting checkbox visibility on the checked state at various stages in the page life cycle.
Given below is a sample code for a dynamically created checkbox.
protected override void OnInit(EventArgs e)
{
base.OnInit(e);
check = new CheckBox();
check.AutoPostBack = true;
check.Text = "checkbox1";
check.ToolTip = "tooltip for checkbox1";
check.CheckedChanged += new EventHandler(check_CheckedChanged);
this.Form.Controls.Add(check);
Button btn = new Button();
btn.Text = "click me";
btn.Click += new EventHandler(btn_Click);
this.Form.Controls.Add(btn);
}
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
check.Checked = true;
check.Text = "text reassigned.";
check.ToolTip = "tooltip reassigned";
}
}
protected override void OnPreRenderComplete(EventArgs e)
{
base.OnPreRenderComplete(e);
check.Visible = false;
}
The issue here is, when a postback occurs (I click on the button), then I notice in the Page_load event, the checkbox maintains the viewstate of the tooltip and text. However the checked state is changed to false and it fires a CheckedChanged event. Why is the behavior so?
Also, if I set the visibility of the checkbox in either PageLoad() or the OnPreRender() event, the checked state of the checkbox is maintained across postbacks and does not fire a CheckedChanged event.
I'm just curious as to what happens differently when the visibility is changed in the OnPreRenderComplete event so as to have the checkbox default to an unchecked state.
Well I have marked my last answer for deletion, as I didn't understand the question properly.
Well the things you are doing are:
You added the checkbox at runtime in Init event on server side.
Then in page load you set its value to true in the Not Post Back check.
Then you set its visibility to false in OnPreRenderComplete event
When you set the visibility to false on server side, the control is not generated on client side (you can check it by viewing the page source), as control is not created on client side so when you post back the page, the checkbox is created in page init and as it was not on client side so dot net doesn't know about its last value, so you get false for the check box.
If you need to check it more further, change your OnPreRenderComplete event as:
protected override void OnPreRenderComplete(EventArgs e)
{
base.OnPreRenderComplete(e);
//check.Visible = false;
check.Style.Add("display", "none");
}
By above line, the style is being added to the control, so the control is generated on client side but is not visible and you will get its value during the post back.

How to use the FindControl function to find a dynamically generated control?

I have a PlaceHolder control inside of a ListView that I am using to render controls from my code behind. The code below adds the controls:
TextBox tb = new TextBox();
tb.Text = quest.Value;
tb.ID = quest.ShortName.Replace(" ", "");
((PlaceHolder)e.Item.FindControl("ph_QuestionInput")).Controls.Add(tb);
I am using the following code to retrieve the values that have been entered into the TextBox:
foreach (ListViewDataItem di in lv_Questions.Items)
{
int QuestionId = Convert.ToInt32(((HiddenField)di.FindControl("hf_QuestionId")).Value);
Question quest = dc.Questions.Single(q => q.QuestionId == QuestionId);
TextBox tb = ((TextBox)di.FindControl(quest.ShortName.Replace(" ","")));
//tb is always null!
}
But it never finds the control. I've looked at the source code for the page and the control i want has the id:
ctl00_cphContentMiddle_lv_Questions_ctrl0_Numberofacres
For some reason when I look at the controls in the ListViewDataItem it has the ClientID:
ctl00_cphContentMiddle_lv_Questions_ctrl0_ctl00
Why would it be changing Numberofacres to ctl00? Is there any way to work around this?
UPDATE:
Just to clarify, I am databinding my ListView in the Page_Init event. I then create the controls in the ItemBound event for my ListView. But based on what #Womp and MSDN are saying the controls won't actually be created until after the Load event (which is after the Page_Init event) and therefore are not in ViewState? Does this sound correct?
If so am I just SOL when it comes to retrieving the values in my dynamic controls from my OnClick event?
UPDATE 2:
So i changed the code i had in my Page_Init event from:
protected void Page_Init(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
//databind lv_Questions
}
}
to:
protected void Page_Init(object sender, EventArgs e)
{
//databind lv_Questions
}
And it fixed my problem. Still a little confused as to why I want to databind regardless of whether it's a postback or not but the issue is resolved.
It looks like you're adding your textbox to a Placeholder control... but then you're searching a ListViewDataItem container for it later.
Seems to me that you need to search for the Placeholder first, and then search it for the textbox.

Resources