4

I am having trouble getting the input values of dynamically created controls in a ListView.

Here is my ListView:

<asp:ListView ID="lvQuestions" runat="server" DataKeyNames="ProductQuestionId" onitemdatabound="lvQuestions_ItemDataBound"> <LayoutTemplate> <table> <tr runat="server" id="itemPlaceholder"></tr> </table> </LayoutTemplate> <ItemTemplate> <tr> <td><%# Eval("Question") %></td> <td> <asp:PlaceHolder ID="plControl" runat="server" /> <asp:HiddenField ID="hfQuestionId" runat="server" /> </td> </tr> </ItemTemplate> </asp:ListView> <asp:Button ID="btnSubmit" runat="server" Text="Submit" onclick="btnSubmit_Click" /> 

In my ItemDataBound Handler I am adding a TextBox or other control to the Placeholder. The control type is dependent on the item, but to keep it simple lets assume it is always a Textbox. The ID of the control is also dynamic.

// create a textbox control TextBox txtbx = new TextBox(); txtbx.ID = "txtQuestion_" + productQuestionId.ToString(); //productQuestionId is the datakey value of this ListViewItem placeholder.Controls.Add(txtbx); 

When a user clicks on the button I need to be able to get the values they filled out.

In my research I found that I need to first recreate the dynamically added controls in order to get the values of them due to the Page Lifecycle.

Here is what I have in my button handler to recreate the controls:

 foreach (ListViewDataItem item in lvQuestions.Items) { HiddenField hdField = (HiddenField)item.FindControl("hfQuestionId"); PlaceHolder plcHolder = (PlaceHolder)item.FindControl("plControl"); TextBox txtbx = new TextBox(); txtbx.ID = "txtQuestion_" + hdField.Value; plcHolder.Controls.Add(txtbx); } 

then the next block of code in the same handler I re-iterate through the ListViewDataItems and find the control:

 foreach (ListViewDataItem item in lvQuestions.Items) { HiddenField hdField = (HiddenField)item.FindControl("hfQuestionId"); PlaceHolder plcHolder = (PlaceHolder)item.FindControl("plControl"); TextBox txtbx = (TextBox)plcHolder.FindControl("txtQuestion_" + hdField.Value); if (txtbx != null) { Response.Write("TextBox Found:" + txtbx.Text); } } 

The textbox is found, but there is no value. It's like I just wrote over the textboxes with new ones in the previous block. If I remove the previous block of code no textboxes are ever found.

Can someone please help me out with what I am missing here?

Thank you.

3 Answers 3

3

As you've already discovered, this is a life cycle issue. Try creating your dynamic control in the ListView.ItemCreated event instead of the ListView.ItemDataBound event.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you Phaedrus, this worked! I never read anything about creating my controls in ItemCreated event. I moved the creation here and removed my block of code for re-creating the controls in the button submit handler. Thanks again.
1

I think the issue here is that the lifecycle does not have a chance to populate the controls with their submitted values before you are trying to read those values.

Typically, if I was going to do something like this, I would be recreating the controls in the Page_Init event, which happens before the values are loaded into the controls. You could potentially do this in a particular control's Init event also, but that is where the additional controls need to be re-added to the page.

1 Comment

I tried adding the recreation of the controls in the Page_Init. I added the logic, if(Page.IsPostBack && lvQuestions.Visible) thus only re-creating them when the form was submitted and the questions are actually displayed. The controls were not found when doing this.
0

That didn't work for me, so I had to do this in the PreInit call

 protected override void OnPreInit(EventArgs e) { base.OnPreInit(e); foreach (ListViewDataItem item in lvQuestions.Items) { HiddenField hdField = (HiddenField)item.FindControl("hfQuestionId"); PlaceHolder plcHolder = (PlaceHolder)item.FindControl("plControl"); if (hdField != null && plcHolder != null) { TextBox txtbx = new TextBox(); txtbx.ID = "txtQuestion_" + hdField.Value; plcHolder.Controls.Add(txtbx); } } } 

And I moved this method back to the ItemDataBound event

 protected void lvQuestions_ItemDataBound(object sender, ListViewItemEventArgs e) { object datakey = lvQuestions.DataKeys[e.Item.DataItemIndex].Value; //get datakey here TextBox txtbx = new TextBox(); txtbx.EnableViewState = true; txtbx.ID = "txtQuestion_" + datakey.ToString(); //productQuestionId is the datakey value of this ListViewItem PlaceHolder pl = e.Item.FindControl("plControl") as PlaceHolder; HiddenField hf = e.Item.FindControl("hfQuestionId") as HiddenField; if (pl != null) pl.Controls.Add(txtbx); if (hf != null) hf.Value = datakey.ToString(); } 

Then it started working.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.