views:

37

answers:

2

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.

+1  A: 

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.

Andrew
DahlinDev
+1  A: 

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.

Phaedrus
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.
DahlinDev