Получить значения динамически добавленных элементов управления в ListView - PullRequest
4 голосов
/ 17 сентября 2010

У меня проблемы с получением входных значений динамически созданных элементов управления в 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 или другой элемент управления в Placeholder. Тип элемента управления зависит от элемента, но для простоты предположим, что это всегда текстовое поле. Идентификатор элемента управления также является динамическим.

// 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 ]

3 голосов
/ 17 сентября 2010

Как вы уже обнаружили, это проблема жизненного цикла. Попробуйте создать динамический элемент управления в событии ListView.ItemCreated вместо события ListView.ItemDataBound.

1 голос
/ 17 сентября 2010

Я думаю, что проблема здесь в том, что жизненный цикл не имеет возможности заполнить элементы управления их отправленными значениями, прежде чем вы попытаетесь прочитать эти значения.

Как правило, если бы я собирался сделать что-то подобное, я бы воссоздал элементы управления в событии Page_Init, которое происходит до того, как значения загружаются в элементы управления. Вы также можете сделать это в событии Init определенного элемента управления, но именно здесь необходимо повторно добавить дополнительные элементы управления на страницу.

0 голосов
/ 13 марта 2014

Это не сработало для меня, поэтому я должен был сделать это в вызове 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();
    }

Потом все заработало.

...