Search code examples
c#asp.netrepeaterweb-controls

Dynamically give Id to textbox (Server side control) in asp:Repeater


In my <asp:Repeater></asp:Repeater> - There is one hidden field, textbox and button.

When data will be bound, then hidden filed will get User Id like below code

<asp:HiddenField ID="hide" Value='<%#Eval("UserId")%>' runat="server"/>

and ItemDataBound event will be called and in this function, i am getting value from hidden field and concatenating that value as a Id in text box. like below code

            TextBox txt = (TextBox)e.Item.FindControl("txtReplyArea");
            HiddenField hf = (HiddenField)e.Item.FindControl("hide");//1
            txt.ID = "txtReplyArea" + hf.Value;//txtReplyArea1

Suppose only one record comes from database and their UserId is 1. Then textbox Id should be "textReplyArea1". From now, all are correct.

I am not sure, it's correct way to giving dynamic Id to repeater control but i think, it's correct.

Problem -

When i click on button and i get a items from repeater and textbox from Id by finding control from repeater then it shows null.

        int areaId = int.Parse((sender as Button).CommandArgument);//1
        string id="txtReplyArea"+areaId;//txtReplyArea1

        foreach (RepeaterItem item in repeaterBlog.Items)
        {
            TextBox tb = item.FindControl(id) as TextBox;//tb = null
        }

Code of aspx page

<%@ Page Title="Messages" Language="C#" MasterPageFile="~/Menu.master" AutoEventWireup="true" CodeFile="Messages.aspx.cs" Inherits="Messages" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" Runat="Server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
    <div style="width:70%;">
        <asp:Repeater ID="repeaterBlog" runat="server" OnItemDataBound="repeaterBlog_ItemDataBound">
        <HeaderTemplate>
            <table>
            </HeaderTemplate>
                <ItemTemplate>
                    <tr >
                        <td>
                            <asp:HiddenField ID="hide" Value='<%#Eval("UserId")%>' runat="server"/>
                            <asp:TextBox  ID="txtReplyArea" runat="server" TextMode="Multiline" Columns="70" Rows="8" Visible="false"></asp:TextBox>
                        </td>
                    </tr>
                    <tr>
                        <td style="margin-left:47%;">
                            <asp:Button ID="btnReply" runat="server" Text="Reply" OnClick="btnReplyClicked" AutoPostBack="True" CommandArgument='<%#Eval("UserId")%>'/>
                        </td>
                    </tr>

                </ItemTemplate>
                <FooterTemplate>
            </table>
                </FooterTemplate>
        </asp:Repeater>

    </div>
</asp:Content>

Code of aspx.cs

            SqlCommand cmd;
            SqlDataReader sdr;
           protected void Page_Load(object sender, EventArgs e)
           {
              if(!IsPostBack)
              { 
    String cs = ConfigurationManager.ConnectionStrings["myWebsite"].ConnectionString;
    using (SqlConnection con = new SqlConnection(cs))
        {

            cmd = new SqlCommand("select * from ContactMessage", con);
            con.Open();
            sdr = cmd.ExecuteReader();

            repeaterBlog.DataSource = sdr;
            repeaterBlog.DataBind();
            con.Close();
        }
    }

}

public void repeaterBlog_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
    if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
    {
        TextBox txt = (TextBox)e.Item.FindControl("txtReplyArea");
        HiddenField hf = (HiddenField)e.Item.FindControl("hide");
        txt.ID = "txtReplyArea" + hf.Value;
    }
}


protected void btnReplyClicked(object sender, EventArgs e)
{
    int areaId = int.Parse((sender as Button).CommandArgument);
    string id="txtReplyArea"+areaId;

    foreach (RepeaterItem item in repeaterBlog.Items)
    {
        TextBox tb = item.FindControl(id) as TextBox;
    }

}

}

Solution

  • This worked for me. Notice that I removed EnableViewState from the repeater and added OnItemDatabound event.

    <asp:Repeater ID="repeaterBlog" runat="server" OnItemDataBound="repeaterBlog_ItemDataBound">
        <HeaderTemplate>
            <table>
        </HeaderTemplate>
        <ItemTemplate>
            <tr>
                <td>
                    <asp:HiddenField ID="hide" Value='<%#Eval("UserId")%>' runat="server" />
                    <asp:TextBox ID="txtReplyArea" runat="server" TextMode="Multiline" Columns="70" Rows="8"
                        Visible="false"></asp:TextBox>
                </td>
            </tr>
            <tr>
                <td style="margin-left: 47%;">
                    <asp:Button ID="btnReply" runat="server" Text="Reply" OnClick="btnReplyClicked" AutoPostBack="True"
                        CommandArgument='<%#Eval("UserId")%>' />
                </td>
            </tr>
        </ItemTemplate>
        <FooterTemplate>
            </table>
        </FooterTemplate>
    </asp:Repeater>
    
        protected void Page_Load(object sender, EventArgs e)
        {
            DataTable dt = new DataTable();
            dt.Columns.Add("UserId");
            DataRow dr = dt.NewRow();
            dr[0] = 34;
            dt.Rows.Add(dr);
            repeaterBlog.DataSource = dt;
            repeaterBlog.DataBind();
        }
    
        public void repeaterBlog_ItemDataBound(object sender, RepeaterItemEventArgs e)
        {
            if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
            {
                TextBox txt = (TextBox)e.Item.FindControl("txtReplyArea");
                HiddenField hf = (HiddenField)e.Item.FindControl("hide");
                txt.ID = "txtReplyArea" + hf.Value;
            }
        }
    
    
        protected void btnReplyClicked(object sender, EventArgs e)
        {
            int areaId = int.Parse((sender as Button).CommandArgument);
            string id = "txtReplyArea" + areaId;
    
            foreach (RepeaterItem item in repeaterBlog.Items)
            {
                TextBox tb = item.FindControl(id) as TextBox;
            }
        }