I have a nested repeater control that displays a list of data, in my case it is an FAQ list. here is the design portion:
<asp:Repeater ID="lists" runat="server">
<ItemTemplate>
<h2 class="sf_listTitle"><asp:Literal ID="listTitle" runat="server"></asp:Literal></h2>
<p class="sf_controlListItems">
<a id="expandAll" runat="server">
<asp:Literal ID="Literal1" runat="server" Text="<%$Resources:ExpandAll %>"></asp:Literal>
</a>
<a id="collapseAll" runat="server" style="display:none;">
<asp:Literal ID="Literal2" runat="server" Text="<%$Resources:CollapseAll %>"></asp:Literal>
</a>
</p>
<ul class="sf_expandableList" id="expandableList" runat="server">
<asp:Repeater ID="listItems" runat="server">
<HeaderTemplate>
</HeaderTemplate>
<ItemTemplate>
<li>
<h1 id="headlineContainer" runat="server" class="sf_listItemTitle">
<a id="headline" runat="server" title="<%$Resources:ClickToExpand %>"></a>
</h1>
<div id="contentContainer" runat="server" class="sf_listItemBody" style="display:none;">
<asp:Literal ID="content" runat="server"></asp:Literal>
</div>
</li>
</ItemTemplate>
<FooterTemplate>
</FooterTemplate>
</asp:Repeater>
</ul>
</ItemTemplate>
</asp:Repeater>
The repeater that I am interested in is the second repeater, listItems. In my code-behind, I cannot directly call listItems and see the controls inside of it. I tried to grab the control inside of list.DataBinding (maybe I need to use a different event?) method:
void lists_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
var oRepeater = (Repeater) lists.FindControl("listItems");
}
but this comes up as null. Can anyone give me some pointers/tips of what I need to do to gain access to the listItems repeater and it's children controls?
Thanks!
lists
belongs to each RepeaterItem, not directly to the Repeater itself.
Try :-
void lists_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if ( e.Item.ItemType == ListItemType.AlternatingItem
|| e.Item.ItemType == ListItemType.Item )
{
Repeater oRepeater = (Repeater)e.Item.FindControl("listItems");
// And to get the stuff inside.
foreach ( RepeaterItem myItem in oRepeater.Items )
{
if ( myItem.Item.ItemType == ListItemType.AlternatingItem
|| myItem.Item.ItemType == ListItemType.Item )
{
Literal myContent = (Literal)myItem.FindControl("content");
// Do Something Good!
myContent.Text = "Huzzah!";
}
}
}
}
And you should be good :)
Edited to incorporate DavidP's helpful refinement.
You need to change that line to
var oRepeater = (Repeater) e.Item.FindControl("listItems");
You're close! Inside your event handler check the RepeaterItemEventArgs for what kind of row you're dealing with. Your child repeater will only be available on (Alt)Item rows, not headers or footers. My guess is that it's blowing up on the header.
Related
I have a repeater inner another repeater and this second one i have a list of checkbox and i need to get the value of the checked.
This is my front code:
<asp:Repeater runat="server" ID="rptPerfis" OnItemDataBound="ItemBound">
<ItemTemplate>
<div class="mws-form-row">
<ul class="mws-form-list inline" style="float: none; display: inline;">
<li style="padding-top: 10px;">
<%# rptNome(Container) %></li>
</ul>
<asp:Repeater runat="server" ID="rptUsers">
<ItemTemplate>
<div class="mws-form-item radioPermissoes clearfix" style="float: none;">
<ul class="mws-form-list inline">
<li>
<asp:CheckBox runat="server" Text="<%# rptAdministradorNome(Container) %>" ID="checkUser" CssClass="<%# rptAdministradorPostClass(Container) %>" /></li>
</ul>
</div>
</ItemTemplate>
</asp:Repeater>
</div>
<br />
<hr />
</ItemTemplate>
</asp:Repeater>
<asp:LinkButton runat="server" ID="fLnkSalvar" class="mws-ic-16 ic-disk" OnClick="fLnkSalvar_Click">Salvar</asp:LinkButton>
and this is how i fill this repeater:
protected void Page_Load(object sender, EventArgs e)
{
listaAdm = Servicos.AdministradorMySql.ListarEmpresa(denuncia.Empresa).OrderByDescending(x => x.Nome).ToList();
todosPerfis = Servicos.Perfil.ListarTodos().ToList();
rptPerfis.DataSource = todosPerfis.Where(x => x.Ativo).OrderBy(x => x.Nome);
rptPerfis.DataBind();
}
protected void ItemBound(object sender, RepeaterItemEventArgs args)
{
if (args.Item.ItemType == ListItemType.Item || args.Item.ItemType == ListItemType.AlternatingItem)
{
int idPerfil = ((Perfil)args.Item.DataItem).ID;
Repeater childRepeater = (Repeater)args.Item.FindControl("rptUsers");
childRepeater.DataSource = listaAdm.Where(x => x.Perfil > 1 && x.Perfil == idPerfil).ToList();
childRepeater.DataBind();
}
}
protected void fLnkSalvar_Click(object sender, EventArgs e)
{
Administrador usuario = new Administrador();
usuario.Permissoes = new List<string>();
// i need to get this values here to fill this `List<string>` and then save
foreach (var x in usuario.Permissoes)
{
Servicos.Denuncia.InserirUsuarios(denuncia.ID, x);
}
}
I've no idea how can i get this values or if there another easier way without add in the list i think its better
You have to use FindControl on multiple levels. First the correct Item in the parent Repeater, then find the CheckBox in the correct Item of the child Repeater.
var cb = ((Repeater)rptPerfis.Items[i].FindControl("rptUsers")).Items[j].FindControl("checkUser") as CheckBox;
PS you need to wrap the code in Page_Load in an IsPostBack check or you will never retrieve the correct checkbox state in a PostBack.
I have a template:
<asp:Repeater ID="litFolder" runat="server" OnItemDataBound="litFolder_ItemDataBound">
<HeaderTemplate>
<ul class="test" id="currentLink">
</HeaderTemplate>
<ItemTemplate>
<div class="leftNav">
<li>
<asp:HyperLink ID="innerHyperLink" runat="server"></asp:HyperLink>
</li>
</div>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
and I'm trying to set the to display block when a link is selected. I can set the link to display block, but how do I set the ul to display block ( only using C# )
protected void litFolder_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
// if the child from the first repeater has children, it will grab them here
Item innerItem = (Item)e.Item.DataItem;
if (innerItem != null)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
// this creates a link to the page in sitecore once clicked
HyperLink topNavigation = (HyperLink)e.Item.FindControl("innerHyperLink");
topNavigation.NavigateUrl = LinkManager.GetItemUrl(innerItem);
topNavigation.Text = innerItem["Title"];
if (topNavigation != null) {
//this is where I think I need to define the ul to display block
}
}
}
}
I need to make sure that the current link sets the ul that it is in and not all the ul's with the class test.
In order to prevent the Ul from being broken, place the <div class="leftNav"> inside the <li> as shown below:
<asp:Repeater ID="litFolder" runat="server" OnItemDataBound="litFolder_ItemDataBound">
<HeaderTemplate>
<ul class="test" id="currentLink">
</HeaderTemplate>
<ItemTemplate>
<li>
<div class="leftNav">
<asp:HyperLink ID="innerHyperLink" runat="server"></asp:HyperLink>
</div>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
To set the display block style, you can find the control based on the ID, then set the style to it.
Thanks
Kinda of confusing title.
This is my old navigation
<li><i class="home"></i> Overview</li>
The i class sets an icon next to the navigation tab.
On the Site.Master.CS I checked what the current page was and would set it to active with the code below.
currentGeneral.Attributes["class"] = "active";
So I changed the navigation to a listview populated by a database.
<asp:ListView ID="ListViewMenu" runat="server" ItemPlaceholderID="menuContainer">
<LayoutTemplate>
<ul class="menu" id="responsive" runat="server">
<asp:PlaceHolder ID="menuContainer" runat="server" />
</ul>
</LayoutTemplate>
<ItemTemplate>
<li><a href='<%#Eval ("href") %>' class='<%#Eval ("id") %>'> <i class='<%#Eval ("class") %>'></i><%#Eval ("text") %></a></li>
</ItemTemplate>
</asp:ListView>
But now that I am using listview, the currentGeneral id does not exist and I cant set it to active.
I was trying to think what the best way to get this to work is. Anyone have a suggestion?
Thank you.
If you want to access individual item inside of ListView while binding, you might want a different approach using ItemDataBound event.
Please make sure to cast DataItem to appropiate object. For example, DataRowView
<asp:ListView ID="ListViewMenu" runat="server"
OnItemDataBound="ListViewMenu_ItemDataBound"
ItemPlaceholderID="menuContainer">
<LayoutTemplate>
<ul class="menu" id="responsive" runat="server">
<asp:PlaceHolder ID="menuContainer" runat="server" />
</ul>
</LayoutTemplate>
<ItemTemplate>
<li>
<asp:HyperLink runat="server" ID="HyperLink1" >
<i class='<%#Eval ("class") %>'></i><%#Eval ("text") %>
</asp:HyperLink>
</li>
</ItemTemplate>
</asp:ListView>
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
PopulateMenu();
}
}
protected void ListViewMenu_ItemDataBound(
object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
var rowView = e.Item.DataItem as DataRowView;
var hyperLink = e.Item.FindControl("HyperLink1") as HyperLink;
hyperLink.NavigateUrl = rowView["href"].ToString();
hyperLink.CssClass = rowView["menu"].ToString();
if (Request.Path.ToLower().Contains(rowView["href"].ToString()))
hyperLink.CssClass += " active";
}
}
void PopulateMenu()
{
DataAccess da = new DataAccess();
da.AddParameter("ID", ID, DataAccess.SQLDataType.SQLInteger, 4);
SiteMenu = da.runSPDataSet("Portal_MenuCreate");
ListViewMenu.DataSource = SiteMenu;
ListViewMenu.DataBind();
}
I have the following data-bound repeater code :
<%--categories--%>
<asp:Repeater ID="CategoryRepeater" runat="server" OnItemDataBound="ItemBound">
<ItemTemplate>
<div class="groupbox">
<fieldset>
<legend><%# Container.DataItem %></legend>
<table>
<asp:Repeater ID="ItemRepeater" runat="server">
<ItemTemplate>
<tr>
<td>
<asp:CheckBox id="chkItem" runat="server" Text='<%# Eval("Text")%>' />
<asp:HiddenField id="pgNos" runat="server" Value='<%# Eval("PGNos")%>' />
<asp:Button ID="btnXRefs" Text="x-refs" runat="server" CssClass="xRefButton" OnClick="btnSelectXRefs_Click" />
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
</fieldset>
</div>
</ItemTemplate>
</asp:Repeater>
There is a repeater inside a repeater. How do I access the text inside the legend (<legend><%# Container.DataItem %></legend>) from code?
I tried :
foreach (RepeaterItem cr in CategoryRepeater.Items)
{
string heading = (string) cr.DataItem; // returns null
}
Container.DataItem is a runtime alias for the DataItem for this specific item in the bound list. For a Repeater which displays 10 rows of data, this is one row from the datasource...Basically, it's a specific row and at runtime you can get the Property Values from this row
I saw your above Mark Up...Seems like you are missing to mention the property of Data-Bound type Class like below.
<%# ((Your Class Name)Container.DataItem).Class Property Name %>
There is a repeater inside a repeater. How do I access the text inside
the legend (<%# Container.DataItem %>) from code?
As told by phemt.latd, you can change the Legend tag into server side control like below.
<legend id="lg" runat="server">
<%# ((Your Class Name)Container.DataItem).Class Property Name %>
</legend>
Now, in the Item-Bound Data Event, Find the Legend Control.
protected void rpt_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
HtmlGenericControl ctl = (HtmlGenericControl)e.Item.FindControl("lg");
ctl.InnerText //This is what will give you the result.
}
}
The legend tag that you use is not visible on server side. Is a client control and not a server one.
Try with this:
<legend id="myLegend" runat="server"><%# Container.DataItem %></legend>
Then in codebehind:
protected void ItemBound(Object sender, RepeaterItemEventArgs e)
{
if (e.Item.DataItem == null) return;
HtmlGenerics body = (HtmlGenerics)e.Item.FindControl("myLegend");
body.InnerText = "Foo";
}
I have a search results page where the list views visible property is always false on the first page load even though I set the value to true as seen below. It seems line is being ignored? Is there a reason why this property cannot be set on the first load?
EDIT: Page load Event
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (Request.QueryString["query"] != null)
{
_searchTerm = Request.QueryString["query"].ToString();
GetSearchResults();
txtSearchBox.Text = _searchTerm;
}
}
}
ListView Markup
<asp:PlaceHolder runat="server" ID="SearchResults" Visible="false">
...
<asp:ListView id="lvSearch" runat="server">
<LayoutTemplate>
<ul id="SearchResultsList">
<asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder>
</ul>
</LayoutTemplate>
<ItemTemplate>
<li class="searchResult">
<h2><%#DataBinder.Eval(Container.DataItem, "Title")%></h2>
<p><%#DataBinder.Eval(Container.DataItem, "HighlightedPreview")%></p>
<%#DataBinder.Eval(Container.DataItem, "URL")%>
</li>
</ItemTemplate>
</asp:ListView>
<div runat="server" id="NoResults" visible="false">
<p>The current search has returned no results. Please enter another search term in the box above.</p>
</div>
</asp:PlaceHolder>
Check that it is not in the DIV-NoResults or some other container that is going invisible.