获取ListView中动态添加的控件的值

时间:2010-09-16 21:56:29

标签: asp.net listview dynamic controls

我无法在ListView中获取动态创建的控件的输入值。

这是我的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" />

在我的ItemDataBound处理程序中,我将一个TextBox或其他控件添加到占位符。控件类型取决于项目,但为了保持简单,我们假设它始终是一个文本框。控件的ID也是动态的。

// 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);

当用户点击按钮时,我需要能够获得他们填写的值。

在我的研究中,我发现我需要首先重新创建动态添加的控件,以便根据页面生命周期获取它们的值。

以下是我在按钮处理程序中重新创建控件的内容:

    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);
    }

然后在同一个处理程序中的下一个代码块我重新遍历ListViewDataItems并找到控件:

    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);
        }
    }

找到了文本框,但没有任何价值。这就像我刚刚在上一个块中用新的文本框写了一样。如果我删除了上一段代码,则找不到任何文本框。

有人可以帮助我解决我在这里缺少的事情吗?

谢谢。

3 个答案:

答案 0 :(得分:3)

正如您已经发现的那样,这是一个生命周期问题。尝试在ListView.ItemCreated事件中创建动态控件,而不是ListView.ItemDataBound事件。

答案 1 :(得分:1)

我认为这里的问题是,在您尝试读取这些值之前,生命周期没有机会使用其提交的值填充控件。

通常情况下,如果我要做这样的事情,我会重新创建Page_Init事件中的控件,这些控件在将值加载到控件之前发生。您也可以在特定控件的Init事件中执行此操作,但这是需要将其他控件重新添加到页面的位置。

答案 2 :(得分:0)

这对我不起作用,所以我必须在PreInit调用中执行此操作

    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);
            }
        }

    }

我将此方法移回ItemDataBound事件

   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();
    }

然后它开始工作。