3

I'm unable to find a Literal inside a Repeater that is in another UserControl.

I have the following UserControl:

<nav role="navigation">
<ul>
    <li><a href="/"<asp:Literal id="litNavHomeActive" runat="server" />>Home</a></li>
<asp:Repeater id="rpt_NavItem" runat="server" OnItemDataBound="rpt_OnItemDataBound">
<ItemTemplate>
    <li><a href="/<asp:Literal id="lit_Url" runat="server" />/"<asp:Literal id="lit_NavActive" runat="server" />><asp:Literal id="lit_Title" runat="server" /></a></li>
</ItemTemplate>
</asp:Repeater>
</ul>
<div class="cb"></div>
</nav>

This is placed inside a MasterPage and from another ContentPage, I'm trying to find "lit_NavActive" and hide it.

I am using this:

Repeater rpt = ((Theme)Page.Master).FindControl("Navigation").FindControl("rpt_NavItem") as Repeater;
Literal lit = rpt.FindControl("lit_NavActive");
if (lit != null) { lit.Visible = false; }

And its not working, if I do rpt.Visible = false; that works fine in hiding the whole repeater, so I'm close but fail to find the Literal (lit_NavActive) inside the Repeater. Any ideas?

Nelson Pires
  • 321
  • 4
  • 12

3 Answers3

4

You need to find the control on a RepeaterItem, not on the Repeater self

foreach (var item in rpt.Items)
{
   Literal lit = item.FindControl("lit_NavActive");
   if (lit != null) { lit.Visible = false; }
}

Remember that a Repeater "repeats" items, so there may be multiple literals within your Repeater. The above code hides will all the Literals.

If you need to hide a "specific" on, then in the loop, you should apply your condition and decide whether to show or hide it.

Alternatively consider using ItemDataBound event of the Repeater.

Niels Filter
  • 4,430
  • 3
  • 28
  • 42
1

Since the repeater is a data bound control, each row of the repeater would consist of a literal named "lit_NavActive". Because of this, it names them uniquely on the page. If you view the source of your page, you would notice them named something like this:

rpt_NavItem_ctl101_lit_NavActive
rpt_NavItem_ctl102_lit_NavActive
rpt_NavItem_ctl103_lit_NavActive

So when you try to find "lit_NavActive" on the entire repeater, it can't find it because "lit_NavActive" doesn't exist like that. What you need to do is find "lit_NavActive" within a row of the repeater.

foreach(RepeaterItem item in rpt_NavItem.Items)
{
    Literal lit_NavActive = (Literal)item.FindControl("lit_NavActive");
    if (lit_NavActive != null) 
    { 
        lit_NavActive.Visible = false; 
    }
}

Edit: It's possible all this stuff:

<li><a href="/<asp:Literal id="lit_Url" runat="server" />/"<asp:Literal id="lit_NavActive" runat="server" />><asp:Literal id="lit_Title" runat="server" /></a></li>

is causing some problems with the opening and closing of controls. I would recommend switching to an <asp:HyperLink>. This will make everything much cleaner and easier to deal with.

<asp:Repeater id="rpt_NavItem" runat="server" 
    OnItemDataBound="rpt_OnItemDataBound">
    <ItemTemplate>
        <asp:HyperLink ID="hyp" runat="server"></asp:HyperLink>
    </ItemTemplate>
</asp:Repeater>

Then in your ItemDataBound handler, set the properties of the HyperLink rather than the Literals.

protected void rpt_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
    HyperLink hyp = (HyperLink)e.Item.FindControl("hyp");
    hyp.NavigateUrl = // your lit_Url value (ex. "http://www.google.com")
    hyp.CssClass = // your lit_NavActive value (ex. "active")
    hyp.Text = // your lit_Title value (ex. "Google")
}

Then getting back to your original foreach loop, find the HyperLink instead.

foreach(RepeaterItem item in rpt_NavItem.Items)
{
    HyperLink hyp = (HyperLink)item.FindControl("hyp");
    if (hyp != null) 
    { 
        hyp.Visible = false; 
    }
}
j.f.
  • 3,908
  • 2
  • 29
  • 42
  • Still cant find it. I have clientIDMode="Static" in web.config so all server IDs dont have (ctl) prefix. The rendered control: Note the class in the Cats anchor, the literal exists per each Item but on most times its text is set to empty. The codes suggested above do not work and I wonder why. – Nelson Pires Jun 04 '15 at 16:08
  • So the text of lit_NavActive would be something like `class="active"`? – j.f. Jun 04 '15 at 16:32
  • Correct, or totally blank. – Nelson Pires Jun 04 '15 at 16:56
  • Well where do you actually set the text, in `rpt_OnItemDataBound`? I don't see where that is being done. – j.f. Jun 04 '15 at 17:02
  • Yes with `((Literal)e.Item.FindControl("lit_NavActive")).Text = " class=\"active\"";` – Nelson Pires Jun 04 '15 at 17:15
  • So then is there a condition or anything that would stop "lit_NavActive" from having any text value set (causing it to be empty like you mention)? – j.f. Jun 04 '15 at 18:23
  • It never get set empty, the only condition is `if (Request.QueryString["par1"] == Url) { ((Literal)e.Item.FindControl("lit_NavActive")).Text = " class=\"active\""; }` which sets the `Literal` text once and only once. This is done in `rpt_OnItemDataBound`. – Nelson Pires Jun 04 '15 at 20:21
  • But are there times it _doesn't_ get set? The literal starts off as empty. So if you don't set it to anything, it would stay empty. Does `Request.QueryString["par1"] == Url` ever return false when debugging it? – j.f. Jun 04 '15 at 20:23
  • Yes, most iterations through the repeater the `Literal` never gets set, on one occasion the condition is met and then the text is set, so the page I'm testing, the text is set but still cant find the `Literal`. – Nelson Pires Jun 04 '15 at 21:06
  • Ok, so that explains why some of them are empty. See my latest edit. I think changing to an `` may be beneficial. You may have conflicting endings and closings to your various controls. – j.f. Jun 04 '15 at 21:18
0

I've seen many of these answers, but I was looking to pass the control in the repeater item into a method, from within the template itself (in the "HTML")

And the answer for doing that I haven't seen, but is that you can do:

Container.FindControl("lit_NavActive")

Container is the RepeaterItem you are currently in.

<asp:Checkbox id="chkValue" Checked='<%# GetCheckboxValue((CheckBox)Container.FindControl("chkValue"), Eval("SettingValue")) %.' />

In this case I was using it to turn the control red if the setting value was not a valid Boolean.

Roger Willcocks
  • 1,649
  • 13
  • 27