C# – Why is FindControl not working with the repeater

asp.netcrepeater

I'm trying to change the visibility of a pair of server controls (specifically a LinkButton and Label) that are nested inside the ItemTemplate part of a repeater during the onclick event of the same LinkButton. I've actually already found a solution, but I don't understand why it works and not the way I was trying before. What I was trying originally is as follows:

Nested inside the ItemTemplate of a repeater

<asp:LinkButton ID="lnAdd" CommandArgument='<%#Eval("index") %>' runat="server" Text="Add" OnClick="lnAdd_Click"> </asp:LinkButton>

<asp:Label Visible="false" runat="server" ID="videoAdded" Text="Video Added"></asp:Label>

Then inside of that lnAdd_Click function I have:

Repeater1.FindControl("lnAdd").Visible = false;
Repeater1.FindControl("videoAdded").Visible = true;

where Repeater1 is the id of the repeater these controls are in. This appears to do nothing (though it compiles). I assume this is because for some unknown reason those controls are not found.

What does work is the last answer of the following question: Server controls in an asp.net repeater

The solution appears to be doing something very similar what I've tried to do. Its even using FindControl on a repeater. The only difference (that I can see) is that it obtains the repeater via the sender object. Hmmm, actually, now that I think about it the id of the elements are changed by .Net to some nonesense like ctl00_ContentPlaceHolder1_Repeater1_ctl02_lnAdd when this is actually run, so perhaps that's why its not finding it. But at the same time, in the working solution I just give the normal ID like "lnAdd". Is .Net automatically translating it? Why would it do it for this solution and not for how I was trying to do it originally?

Anyway, I feel like there's something fundamental here that I'm not quite grasping and would appreciate some enlightenment 😀

Best Answer

The problem with using Repeater1.FindControl(..)... is that you can't tell which particular Label or LinkButton is being targeted. It's a repeater, so each such item gets assigned a unique identifier as part of the RepeaterItemCollection. In the markup you name it "lnAdd" but that's not what it will be once generated etc.

For reference, here's the code you said worked from the other post:

protected void btnUpdate_OnClick(object sender, EventArgs e)
    {
        Button b = sender as Button;
        if (b != null)
        {
            RepeaterItem ri = b.Parent as RepeaterItem;
            if (ri != null)
            {
                string name = null;

                //Fetch data
                TextBox txtName = ri.FindControl("txtName") as TextBox;

I'll explain the reason the above works. First, the button that was clicked is cast from the sender object. We know it's a button since it's the Update button's click handler. Next, we also know that the button appears in a repeater, so it's parent is a RepeaterItem. That's how the ri variable is initialized and cast. With ri available to us, using FindControl on it will now find the given control in that particular RepeaterItem.