Getting values from textbox in the repeater in button click event

user1928473 picture user1928473 · Jul 17, 2013 · Viewed 9.8k times · Source

I have a TextBox in a repeater that is populated from the database in the ItemDataBound event. When I tried to get the text inside the TextBox in a Button_Click event I found the TextBox.Text empty. How can I get the Text?

    foreach (RepeaterItem repeated in repEdit.Items)
    {
        DropDownList drp = (DropDownList)FindControlRecursive(repeated, "drpdown");
        TextBox txt = (TextBox)FindControlRecursive(repeated, "txt");
        CheckBox chk = (CheckBox)FindControlRecursive(repeated, "chk");
        if (drp != null && !string.IsNullOrEmpty(drp.Attributes["ID"]))
        {
            loc.GetType().GetProperty(drp.Attributes["ID"].Split('#')[0] + "ID").SetValue(loc, int.Parse(drp.SelectedValue), null);
        }
        if (txt != null && !string.IsNullOrEmpty(txt.Attributes["ID"]))
        {
            if (txt.Attributes["ID"].Contains("#int"))
            {
                loc.GetType().GetProperty(txt.Attributes["ID"].Split('#')[0]).SetValue(loc, int.Parse(txt.Text), null);    
            }
            else if (txt.Attributes["ID"].Contains("#decimal"))
            {
                loc.GetType().GetProperty(txt.Attributes["ID"].Split('#')[0]).SetValue(loc, decimal.Parse(txt.Text), null);    
            }
            else
            {
                loc.GetType().GetProperty(txt.Attributes["ID"].Split('#')[0]).SetValue(loc, txt.Text, null);    
            }
        }
        if (chk!=null && !string.IsNullOrEmpty(chk.Attributes["ID"]))
        {
            loc.GetType().GetProperty(chk.Attributes["ID"].Split('#')[0]).SetValue(loc, chk.Checked, null);
        }
    }

HTML

<asp:Repeater ID="repEdit" runat="server" OnItemDataBound="repEdit_ItemDataBound">
        <ItemTemplate>
            <asp:Label ID="lblName" runat="server" Visible="false"></asp:Label>
            <asp:TextBox ID="txt" runat="server" Visible="false"></asp:TextBox>
            <asp:CheckBox ID="chk" runat="server" Visible="false" />
            <asp:DropDownList ID="drpdown" runat="server" Visible="false">
            </asp:DropDownList>
            <br />
        </ItemTemplate>
</asp:Repeater>

Here is the itemdatabound event

protected void repEdit_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            Label name = e.Item.FindControl("lblName") as Label;
            TextBox text = e.Item.FindControl("txt") as TextBox;
            CheckBox chk = e.Item.FindControl("chk") as CheckBox;
            DropDownList drp = e.Item.FindControl("drpdown") as DropDownList;
            Button but = e.Item.FindControl("butEdit") as Button;
            //butEdit.Visible = true;
            if (but != null)
            {
                but.Visible = true;
            }
            if (e.Item.ItemType == ListItemType.Item)
            {
                KeyValuePair<string, Dictionary<int, string>> kvp = (KeyValuePair<string, Dictionary<int, string>>)e.Item.DataItem;
                if (name != null)
                {
                    if (kvp.Key.Contains("#datetime"))
                    {
                        return;
                    }
                    name.Visible = true;
                    name.Text = kvp.Key.Split('#')[0].ToString();
                }
                if (kvp.Key.Contains("#int") || kvp.Key.Contains("#decimal"))
                {
                    text.Visible = true;
                    text.ID = kvp.Key;
                    text.EnableViewState = true;
                    text.Attributes["ID"] = kvp.Key;
                    text.Text = kvp.Value[0].ToString();
                    if (kvp.Key.Split('#')[0] == "ID")
                    {
                        text.Enabled = false;
                    }
                }

Answer

Adam picture Adam · Jul 2, 2014

Here is your Repeater. It has a PlaceHolder and Button.

<asp:Repeater ID="rpNotifications" runat="server" 
              OnItemDataBound="rpNotifications_ItemDataBound">
    <ItemTemplate>

         <asp:PlaceHolder ID="commentHolder" runat="server"></asp:PlaceHolder>

         <asp:Button runat="server" ID="btnComment" 
              Text="Comment" CssClass="btn blue" 
              OnClick="btnComment_Click" CommandArgument='<%# Eval("id") %>' />

    </ItemTemplate>
</asp:Repeater>

The button has the command argument set as the Id of the data I am binding to it.

Next here is where you need to Bind your Repeater. If you don't Bind it in the Page_Init the resulting values in the dynamically created controls will be lost.

protected void Page_Init(object sender, EventArgs e)
{

        rpNotifications.DataSource = {datasource-here}
        rpNotifications.DataBind();
}

And here is why (Image from: http://msdn.microsoft.com/en-us/library/ms972976.aspx)

enter image description here

Dynamically Create Control on ItemDataBound You will need to add the textbox to the placeholder as this is the only way to dynamically assign an ID to the control.

protected void rpNotifications_ItemDataBound(object sender, 
                                             RepeaterItemEventArgs e)
{

        if (e.Item.ItemType == ListItemType.Item 
            || e.Item.ItemType == ListItemType.AlternatingItem)
        {

            Common.Models.Item item = (Common.Models.Item)e.Item.DataItem;

            // Create new Control
            TextBox txtComment = new TextBox();
            txtComment.ID = String.Format("txtComment{0}", item.id.ToString());

            // Ensure static so you can reference it by Id
            txtComment.ClientIDMode = System.Web.UI.ClientIDMode.Static;

            // Add control to placeholder
            e.Item.FindControl("commentHolder").Controls.Add(txtComment);
        }
}

Get Value On Button Click Now you need to create the event handler for the button and get the resulting value

protected void btnComment_Click(object sender, EventArgs e)
{
        // This is the ID I put in the CommandArgument
        Guid id = new Guid(((Button)sender).CommandArgument);

        String comment = String.Empty;

        // Loop through the repeaterItems to find your control
        foreach (RepeaterItem item in rpNotifications.Controls)
        {
            Control ctl = item.FindControl(
                               String.Format("txtComment{0}", id.ToString()));

            if (ctl != null)
            {
                comment = ((TextBox)ctl).Text;
                break;
            }
        }

}