Find nested repeater in 3 level repeater - asp.net

I have a 3-level asp.net repeater, and I need to find the 3rd level's items. The code-behind is posted below as well.
Here is my aspx code:
<div class="container">
<asp:Repeater runat="server" ID="rptGrp0" OnItemDataBound="rptGrp0_ItemDataBound">
<HeaderTemplate>
<div id="Grp0" class="rptParent">
</HeaderTemplate>
<ItemTemplate>
<div id="rptParent <%# Eval("Name") %>">
<div class="row-fluid">
<div class="span12">
<h5 class="parentTitle"><%# Eval("Name") %></h5>
</div>
</div>
</div>
<div class="group">
<div id="rptChild <%# Eval("Name") %>">
<div>
<asp:Repeater runat="server" ID="rptGrp1" OnItemDataBound="rptGrp1_ItemDataBound">
<HeaderTemplate>
<div id="Grp1" class="rptChild">
</HeaderTemplate>
<ItemTemplate>
<div class="group">
<div id="rptGrandChildHeader <%# Eval("Name") %>">
<div class="content">
<div class="container">
<div class="row-fluid">
<div class="span12">
<p class="blue">
<asp:Label runat="server" ID="lblChildName" Text='<%# Eval("Name") %>'></asp:Label>
</p>
</div>
</div>
</div>
</div>
</div>
<div id="rptGrandChild <%# Eval("Name") %>">
<asp:Repeater runat="server" ID="rptContent">
<HeaderTemplate>
<div class="c_module">
<div class="container">
<div class="row-fluid">
<div class="span12">
<div class="data_controls">
<div class="clearfix"></div>
</div>
<div class="d_table_module">
<table border="0" class="display" id="tblContent">
<thead>
<tr>
<th>Product</th>
</tr>
</thead>
<tbody>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td style="width:100px;">
<asp:Label runat="server" ID="lblProduct" Text='<%# Eval("Product") %>'></asp:Label>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</FooterTemplate>
</asp:Repeater>
</div>
</div>
</ItemTemplate>
<FooterTemplate>
</div>
</FooterTemplate>
</asp:Repeater>
</div>
</div>
</div>
</ItemTemplate>
<FooterTemplate>
</div>
</FooterTemplate>
</asp:Repeater>
</div>
Here is my code-behind.
protected void lnkButton_Click(object sender, EventArgs e)
{
Repeater primary = (Repeater)this.FindControl("rptGrp0");
if (primary != null)
{
// Items.Count = 0.
foreach (RepeaterItem item in primary.Items)
{
Repeater secondary = (Repeater)item.FindControl("rptGrp1");
if (secondary != null)
{
foreach (RepeaterItem b in secondary.Items)
{
Repeater target = (Repeater)b.FindControl("rptContent");
if (target != null)
{
foreach (RepeaterItem c in target.Items)
{
}
}
}
}
}
}
}
The problem is that my repeater.Items.Count is 0.
Please advise, thanks.

Repeater will display only if it is bounded with DataSource. Make sure your repeaters are bounded with a proper DataSource.

Finding the items of the 3rd repeater depends on how you databind it to begin with. If you are binding data in your Page_Load event, then the data is bound after the click event is processed. On your lnkButton_Click event the contents of the repeaters have not yet been bound. The easiest way to access those items is to have an Item_DataBound event to access those items.
Sample code:
<asp:Repeater runat="server" ID="rptContent" OnItemDataBound="rptContent_ItemDataBound">
...
</asp:Repeater>
Code Behind:
protected void rptContent_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
e.Item; // This current item
Repeater rpt = (Repeater)(sender);
rpt.Items; // All items
//Do some condition here to test on the item for whatever you want to do
if(e.Item == someCondition)
// some operation here
}

Okay I found the solution. It has to do with the ASP.NET page lifecycle.
After the lnkButton_Click event, a postback occurred, but I needed to "rebind" the repeater datasource on postback, not just initial page_load.
e.g.
protected void Page_Load()
{
if (!IsPostBack)
{
// bind control
}
else
{
// rebind control
}
}

Related

How to access the id of a TextBox in the repeater code behind

I have a repeater below;
<asp:Repeater ID="RptRE" runat="server">
<ItemTemplate>
<div id="headingCollapse2" runat="server">
<a data-toggle="collapse" href="#link<%#Eval("IDmessage")%>" aria-expanded="false" aria-controls="link<%#Eval("IDmessage")%>">
<asp:TextBox ID="getid" runat="server"></asp:TextBox>
<div class="media">
<span class="avata">
<img class="media" src="../pics/<%#Eval("Picsender")%>"></span>
</div>
<div class="media">
<h6 class="list"><%#Eval("SubjectMessage")%></h6>
<p class="ltext">
<span><%#Eval("DateSendMessage")%></span>
</p>
</div>
</a>
</div>
<div id="link<%#Eval("IDmessage")%>" role="tabpanel" aria-labelledby="headingCollapse2" class="card-collapse collapse" aria-expanded="false" style="">
<p><%#Eval("ContentMessage")%></p>
</div>
</ItemTemplate>
</asp:Repeater>
In line 5 I have a textbox
<asp:TextBox ID="getid" runat="server"></asp:TextBox>
I can't get the ID of the TextBox code-behind. Is there any specific reason? Does anybody know how to get it?
Thanks
I've made a simple demo with 2 examples of how to get the data out of the Repeater. One example is per row and the other all rows at once. Just make sure you bind data in an IsPostBack check.
<asp:Repeater ID="RptRE" runat="server" OnItemCommand="RptRE_ItemCommand">
<ItemTemplate>
<asp:TextBox ID="getid" runat="server"></asp:TextBox>
<asp:Button ID="Button1" runat="server" Text="This Item" CommandName="Show" />
<hr />
</ItemTemplate>
</asp:Repeater>
<asp:Button ID="Button1" runat="server" Text="All Items" OnClick="Button1_Click" />
<asp:Label ID="Label1" runat="server" Text=""></asp:Label>
Code behind
protected void RptRE_ItemCommand(object source, RepeaterCommandEventArgs e)
{
//get the correct textbox from the ItemIndex
var textbox = (TextBox)RptRE.Items[e.Item.ItemIndex].FindControl("getid");
//show result
Label1.Text = textbox.Text;
}
protected void Button1_Click(object sender, EventArgs e)
{
foreach (RepeaterItem item in RptRE.Items)
{
var textbox = (TextBox)item.FindControl("getid");
Label1.Text += textbox.Text + "<br>";
}
}

WebForms repeater, set CSS class depends on item index

I'm new with WebForms.
Now I'm using Repeater to display item from List collection.
The problem that I need to change css class depends on evenness of item.
My repeater code:
<asp:Repeater runat="server" ID="rptItems">
<ItemTemplate>
<div class="not-even">
<%# Eval("Title") %>
</div>
<ItemTemplate>
</asp:Repeater>
And what I want:
<div class="not-even">
Item 1
</div>
<div class="even">
Item 2
</div>
<div class="even">
Item 3
</div>
<div class="even">
Item 4
</div>
How can I set CSS class depends on evennes of item using repeater?
You can use a ternary operator for that. Check the ItemIndex and set the correct class.
<asp:Repeater ID="rptItems" runat="server">
<ItemTemplate>
<div class="<%# Container.ItemIndex %2 == 1 ? "even" : "not-even" %>">
Item <%# Container.ItemIndex + 1 %>
</div>
</ItemTemplate>
</asp:Repeater>
The obvious solution is AlternatingItemTemplate which is designed for exactly this.
<asp:Repeater runat="server" ID="rptItems">
<ItemTemplate>
<div class="not-even">
<%# Eval("Title") %>
</div>
<ItemTemplate>
<AlternatingItemTemplate>
<div class="even">
<%# Eval("Title") %>
</div>
<AlternatingItemTemplate>
</asp:Repeater>
Less obvious, but arguably simpler, is to just use CSS with :nth-child(odd) and :nth-child(even).
For example, give the repeater a base css class
<asp:Repeater runat="server" ID="rptItems" class="items">
<ItemTemplate>
<div>
<%# Eval("Title") %>
</div>
<ItemTemplate>
</asp:Repeater>
Would result in
.items :nth-child(odd)
{
color:red;
}
.items :nth-child(even)
{
color:blue;
}
<div class="items">
<div>
Item 1
</div>
<div>
Item 2
</div>
<div>
Item 3
</div>
<div>
Item 4
</div>
</div>

ASP.Net ListView Grouping by Data Field?

I uses asp.net listview control to display the details. Each item has the group details. For demo purposes group is hard coded.
I want to display the listview as shown below
Right now, I have this
Code:
<asp:ListView ID="HyperLinkListView" runat="server" ViewStateMode="Disabled" ItemPlaceholderID="itemContainer" GroupPlaceholderID="groupContainer">
<LayoutTemplate>
<section class="quick-links">
<div class="row">
<div class="dfwp-column" style="width: 100%">
<div class="slm-layout-main groupmarker">
<ul class="dfwp-list">
<asp:PlaceHolder ID="groupContainer" runat="server" />
</ul>
</div>
</div>
</div>
</section>
</LayoutTemplate>
<GroupTemplate>
<span>Group</span>
<asp:PlaceHolder ID="itemContainer" runat="server" />
</GroupTemplate>
<ItemTemplate>
<li>
<div class="item">
<div class="link-item">
<asp:HyperLink Target="_blank" ID="hyperlink" NavigateUrl='<%# this.LinkToPlay((((SPListItem)Container.DataItem)["VideoFileName"]).ToString()) %>' Text='<%# Eval("Title") %>' runat="server" />
</a>
</div>
</div>
</li>
</ItemTemplate>
<EmptyDataTemplate>
<span>No data was returned.</span>
</EmptyDataTemplate>
</asp:ListView>
How do I achieve this?
For a flexible solution, you can use nested ListView
You will need to update your HTML and CSS to get the desired appearance.
ASPX Code
<asp:ListView ID="GroupsListView" runat="server" ViewStateMode="Disabled" ItemPlaceholderID="groupContainer" OnItemDataBound="GroupsListView_ItemDataBound">
<LayoutTemplate>
<section class="quick-links">
<div class="row">
<div class="dfwp-column" style="width: 100%">
<div class="slm-layout-main groupmarker">
<asp:PlaceHolder ID="groupContainer" runat="server" />
</div>
</div>
</div>
</section>
</LayoutTemplate>
<ItemTemplate>
<ul class="dfwp-list">
<li><%# Eval("Title") %></li>
<div>
<asp:ListView runat="server" ID="ItemsListView" ItemPlaceholderID="itemContainer">
<LayoutTemplate>
<section class="quick-links">
<div class="row">
<div class="dfwp-column" style="width: 100%">
<div class="slm-layout-main groupmarker">
<ul class="dfwp-list">
<asp:PlaceHolder ID="itemContainer" runat="server" />
</ul>
</div>
</div>
</div>
</section>
</LayoutTemplate>
<ItemTemplate>
<li>
<div class="item">
<div class="link-item">
<asp:HyperLink Target="_blank" ID="hyperlink" NavigateUrl='<%# Eval("Url") %>' Text='<%# Eval("Title") %>' runat="server" />
</a>
</div>
</div>
</li>
</ItemTemplate>
</asp:ListView>
</div>
</ul>
</ItemTemplate>
<EmptyDataTemplate>
<span>No data was returned.</span>
</EmptyDataTemplate>
</asp:ListView>
In the code behind you need to bind the child ListView in parent ItemDataBound event.
protected void GroupsListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
ListView itemsListView = (ListView)e.Item.FindControl("ItemsListView");
if (e.Item.ItemType == ListViewItemType.DataItem)
{
itemsListView.DataSource = ((Group)e.Item.DataItem).Items;
itemsListView.DataBind();
}
}
It is not quite clear what kind of grouping you want. However the ListView is limited in what it can do.
First of all you can only get a grouping by a fixed number of items. You can define that number with the GroupItemCount property. Your code would then look like this
<asp:ListView ID="HyperLinkListView" GroupItemCount="2" runat="server" ViewStateMode="Disabled" ItemPlaceholderID="itemContainer" GroupPlaceholderID="groupContainer">
And generate in html like this
GROUP
My car video
My sample video
GROUP
Another sample video
Item 4
Assuming you want GROUP A and GROUP B etc, you would normally use a binding expression, which looks like this
<GroupTemplate>
<span>Group <%# Container.DataItemIndex %></span>
<asp:PlaceHolder ID="itemContainer" runat="server" />
</GroupTemplate>
However the GroupItemTemplate is not part of the DataBind process, so getting and index based system will not work like that.
So a client side solution is needed if you want to add A, B etc. So first add a placeholder for the alhpa character and give the <span> a class so jQuery can find it. I've used {index} and groupIndex
<GroupTemplate>
<span class="groupIndex">Group {index}</span>
<asp:PlaceHolder ID="itemContainer" runat="server" />
</GroupTemplate>
Now with a simple jQuery method, all the placeholders are replaced with their correct alpha character.
<script type="text/javascript">
$(document).ready(function () {
$('.quick-links .groupIndex').each(function (index, element) {
var char = String.fromCharCode(65 + index);
$(this).html($(this).html().replace('{index}', char));
});
});
</script>
Note that the .quick-links comes from your <section class="quick-links"> part in the LayoutTemplate.

find hidden field value when link button is inside nested repeater

<asp:Repeater ID="rptHotels" runat="server" OnItemDataBound="rptHotels_ItemDataBound">
<ItemTemplate>
<div class="hotel-box">
<div class="hotel-img">
<asp:HiddenField ID="hdnHotelCode" runat="server" Value='<%#Eval("HotelCode")%>' />
<a class="preview" href='<%#Eval("ImageURL_Text") %>' title='<%#Eval("HotelName")%>' target="_blank">
<img src='<%#Eval("ImageURL_Text") %>' alt='<%#Eval("HotelName")%>' height="75px"
width="100px" />
</a>
</div>
<div class="hotel_heeading_content">
<div class="hotel_heading">
<h2>
<asp:LinkButton ID="lnkHotelDetail" runat="server" OnClick="lnkHotelDetail_Click">
<%#Eval("HotelName")%>
(
<%#Eval("boardType")%>)
</asp:LinkButton>
</h2>
</div>
<div class="stars">
<span class="stars">
<%#Eval("StarRating")%></span>
</div>
<div class="hotel_text">
<%#Eval("HotelAddress")%>,
<%#Eval("Destination")%>
,<%#Eval("Country")%>
<img src="images/ico_point2.png" alt="" id="mapicon" class="mapicon" />
<input type="hidden" id="hdnLatitude" class="hdnLatitude" runat="server" value='<%#Eval("Latitude")%>' />
<input type="hidden" id="hdnLongitude" class="hdnLongitude" runat="server" value='<%#Eval("Longitude")%>' />
<input type="hidden" id="hdnInfoWindow" class="hdnInfoWindow" runat="server" />
</div>
</div>
<p>
<asp:Literal ID="ltDes" runat="server"></asp:Literal>
</p>
<p>
more info
</p>
<div class="btn">
<asp:LinkButton ID="lnkPrice" runat="server" Text=' <%#Eval("totalPrice")%>' OnClick="lnkHotelDetail_Click" ></asp:LinkButton>
</div>
<div class="roominfo">
<asp:Repeater ID="rptRooms" runat="server">
<HeaderTemplate>
<div class="rooms">
<div class="roominfoheader">
<div class="roomheaderlbl">
Room Name</div>
<div class="roomheaderlbl">
Total Room Rate</div>
<div class="roomheaderlbl">
Book Now</div>
</div>
</div>
</HeaderTemplate>
<ItemTemplate>
<div class="rooms">
<div class="roominforow">
<div class="roominforowlbl">
<asp:Label ID="lblRoomName" runat="server" Text='<%#Eval("roomCategory") %>'></asp:Label></div>
<div class="roominforowlbl">
$
<asp:Label ID="Label1" runat="server" Text='<%#Eval("totalRoomRate") %>'></asp:Label></div>
<div class="roominforowlbl">
<asp:LinkButton ID="lnkBookNow" runat="server" Text="Book Now" OnClick="lnkBookNow_Click"></asp:LinkButton></div>
</div>
</div>
</ItemTemplate>
</asp:Repeater>
</div>
</div>
</ItemTemplate>
</asp:Repeater>
I have above HTML for nested repeater .I am able to find the hidden field value which contain hotel Code by following method
protected void lnkHotelDetail_Click(object sender, EventArgs e)
{
LinkButton btn = (LinkButton)sender;
var item = (RepeaterItem)btn.NamingContainer;
HiddenField hdnHotelCode = (HiddenField)item.FindControl("hdnHotelCode");
}
but the problem is now i have to find the hidden field value when a nested repeater item template link button is clicked .You can check that lnkBookNow is link button which is inside the rptRooms repeater.
protected void lnkBookNow_Click(object sender, EventArgs e)
{
LinkButton btn = (LinkButton)sender;
var item = (RepeaterItem)btn.NamingContainer;
HiddenField hdnHotelCode = (HiddenField)item.FindControl("hdnHotelCode");
}
I tried something like this but its not finding hidden field.
The problem here is that lnkBookNow.NamingContainer is rptRooms. This control obviously does not contain hdnHotelCode.
I think you should be able to do this with:
protected void lnkBookNow_Click(object sender, EventArgs e)
{
LinkButton btn = (LinkButton)sender;
var item = (RepeaterItem)btn.NamingContainer.NamingContainer.NamingContainer;
HiddenField hdnHotelCode = item.FindControl("hdnHotelCode") as HiddenField;
}
btn.NamingContainer is a RepeaterItem in rptRooms. The NamingContainer of that is the Repeater itself. Finally, the NamingContainer of rptRooms is the RepeaterItem of rptHotels, in which you want to find your HiddenField.
Note my use of the as keyword instead of an explicit cast - this will protect you from NullReferenceExceptions if FindControl returns null. Of course, you should explicitly check that hdnHotelCode isn't null before you try to access it.

Conditional ASP.NET Repeater

It's my Repeater:
<asp:Repeater ID="RepeaterWeb" runat="server">
<ItemTemplate>
<div class="productWrapper">
<div class="productWrapperImage"><img src="prdimg/<%# Trim(Eval("ProductImage")).ToString()%>" /></div>
<div class="fontTrebuchet"><%# Trim(Eval("ProductShortInfo")).ToString()%></div>
<h3 class="fontUbuntu productBoxName"><%# Trim(Eval("ProductName")).ToString()%></h3>
</div>
<!--This div my problem--><div class="verticalProductsSpacer"></div>
</ItemTemplate>
</asp:Repeater>
I feed the Repeater with 4 rows of data from database, first three <div class="verticalProductsSpacer"></div> are necessary but the last one shouldn't be existed. How can I do it?
User a SeparatorTemplate:
<asp:Repeater ID="RepeaterWeb" runat="server">
<ItemTemplate>
<div class="productWrapper">
<div class="productWrapperImage"><img src="prdimg/<%# Trim(Eval("ProductImage")).ToString()%>" /></div>
<div class="fontTrebuchet"><%# Trim(Eval("ProductShortInfo")).ToString()%></div>
<h3 class="fontUbuntu productBoxName"><%# Trim(Eval("ProductName")).ToString()%></h3>
</ItemTemplate>
<SeparatorTemplate>
<div class="verticalProductsSpacer"></div>
</SeparatorTemplate>
</asp:Repeater>
You can use Jquery to hide it.
$('.verticalProductsSpacer').last().css('display', 'none');

Resources