ASP.NET Repeater Template, Conditional Code for every Nth element - asp.net

I'm using an asp.net repeater to create a bunch of images. The image markup is all the same so the standard <ItemTemplate> is fine.
However, I want to wrap K images in a div. Lets say I bind 25+ images to the repeater and I want 5 images per div. How do I go about conditionally creating the start and close tags for the div?
Is this a case better suited for a for loop.

This should work for you, with no need for anything in the code behind (other than binding the repeater..):
<asp:Repeater ID="repImages" runat="server">
<HeaderTemplate><div></HeaderTemplate>
<ItemTemplate>
<%# (Container.ItemIndex != 0 && Container.ItemIndex % 5 == 0) ? #"</div><div>" : string.Empty %>
<asp:Image ID="imgGallery" runat="server" ImageUrl='<%# /* your code here */ %>' />
</ItemTemplate>
<FooterTemplate></div></FooterTemplate>
</asp:Repeater>

Here is where Asp.Net WebForms can give you incredible RAD efficiency.
You can use the new ListView control, and set the number of items per "group", which will allow you to setup the HTML that surrounds a group, as well as each individual item. This way you can surround the group with the conditional tags.
<asp:ListView ID="ListView1" runat="server" DataKeyNames="id" DataSourceID="LinqDataSource1" GroupItemCount="3">
<LayoutTemplate>
<div id="layout">
<asp:PlaceHolder ID="groupPlaceholder" runat="server"></asp:PlaceHolder>
</div>
</LayoutTemplate>
<GroupTemplate>
<div class="group">
<asp:PlaceHolder ID="itemPlaceholder" runat="server"></asp:PlaceHolder>
</div>
</GroupTemplate>
<EmptyDataTemplate>
<span>No data was returned.</span>
</EmptyDataTemplate>
<ItemTemplate>
<div class="item">
<img alt='<%# Eval("title") %>' title='<%# Eval("title") %>'
src='<%# Eval("filename","photos/{0}") %>' />
</div>
</ItemTemplate>
</asp:ListView>

If you want to keep your markup on the ASPX page you could also try this variation on David's method:
On the aspx page:
<ItemTemplate>
<asp:Literal runat="server" ID="divStart" Text="<div>" />
<asp:Image ....>
<asp:Literal runat="server" ID="divEnd" Text="</div>" />
</ItemTemplate>
In the ItemDataBound event in the codebehind:
e.Item.FindControl("divStart").Visible
= e.Item.FindControl("divEnd").Visible
= e.Item.ItemIndex % 5 == 0;

Add two empty label controls into your Repeaters ItemTemplate where you'd want your div tags to be.
Then add an ItemDataBound event to the Repeater.
Then add this code into the ItemDataBound event:
Protected Sub Repeater1_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs)
If (e.Item.ItemType = ListItemType.Item) Or (e.Item.ItemType = ListItemType.AlternatingItem) Then
If e.Item.ItemIndex Mod 5 = 0 Then
Dim lblDivStart As Label = CType(e.Item.FindControl("lblDivStart"), Label)
Dim lblDivEnd As Label = CType(e.Item.FindControl("lblDivEnd"), Label)
lblDivStart.text = "<div>"
lblDivEnd.text = "</div>"
End If
End If
End Sub
Note - This will need some tweaking to handle the first div and you may need to do something like If (e.Item.ItemIndex + 1) Mod 5 = 0 to get the divs to show up exactly where you want them.
For more info:
DataListItem.ItemIndex Property
DataList.ItemDataBound Event

Related

ASP.NET Linkbutton not getting dynamic value for commandargument value

<%
foreach (training t in traininglist)
{
%>
<tr>
<td><%=t.TrainingId%></td>
<td><%=t.TrainingName%></td>
<td>
<asp:LinkButton runat="server" ID="EditBtn"
Text="Edit" OnCommand="editbtn_OnCommand"
CommandArgument='<%# t.TrainingId %>' CommandName="edit" />
</td>
</tr>
<% } %>
where,
training is the class and traininglist is List<training> defined in Page_Load() function in codebehind.
I am trying to call the
public void editbtn_OnCommand(object sender, CommandEventArgs e)
{
String myeid = e.CommandArgument.ToString();
....
}
Here, myeid is not getting value but always shows <%# t.TrainingId %>
i have already tried all other options like <%: t.TrainingId %> or <%=t.TrainingId %>
The output of Tag "<%= %>" is more likely similar to use Response.Write in your code. so these tags are used to display the value to the response object.
That's why,as per my understanding, You can't used these tags to set commandargument property of controls unless you are using DataBinding. If you are using DataBinding then these tags "<%= %>" are used to set the property of controls.
Because you are here looping through each item in list on html table, my suggestion is to use GridView or Repeater and then Bind through your List Object. if you are using this way, you can get rid of unwanted formatting issues of html tables also.
Refer http://msdn.microsoft.com/en-us/library/6dwsdcf5(VS.71).aspx
If you want to use repeater then you can use these specific tags, and this should be your code(not actual code, just sample one)
<asp:Repeater id="myRepeater" runat="server" >
<ItemTemplate>
<div>
<asp:LinkButton runat="server" id="EditBtn" CommandName="edit"
CommandArgument="<%#Container.DataItem.TrainingId %>" Text="Edit"
OnCommand="editbtn_OnCommand" />
</div>
</ItemTemplate>
</asp:Repeater>

Can't find a control in repeateritem.findcontrol

I have a nested repeaters in a form and bind them to tables in a dataset. I can find the controls by name and read and set values in the Itemdatabound event, However I can't find the control by the same name in a button click event. I can find the repeater and the item.
<asp:Repeater ID="rptrDivision" OnItemDataBound="rptrDivision_ItemDataBound" runat="server">
<itemtemplate>
<div class="fluid">
<div class="widget grid12">
<div class="whead"><div class="grid2"><h4 class="fieldDivision" >
<h4 class="fieldDivision" ><asp:Label ID="lblDivName" runat="server" Visible="True" ><%# DataBinder.Eval(Container.DataItem, "LocationName")%></asp:Label></h4></div>
<div class="grid10">
<div class="grid4 divAdmin" ><label><strong>Division Administrator: </strong> </label></div>
<div class="grid8 on_off">
<div class="floatL ml10"><asp:CheckBox ID="cbxDivMgr" name="chbox" runat="server" /></div>
</div>
</div></div>
<asp:Repeater ID="rptrCamera" OnItemDataBound="rptrCamera_ItemDataBound" runat="server" datasource='<%# Container.DataItem.Row.GetChildRows("CameraJoin")%>'>
<HeaderTemplate>
<div class="body">
</HeaderTemplate>
<itemtemplate>
<div class="formRow">
<div class="grid2">
<asp:Label ID="CameraName" runat="server" ><strong><%# Container.DataItem("Name")%></strong></asp:Label> </div>
<div class="grid10" >
<asp:RadioButtonList ID="rblRoles" runat="server" CssClass="mr10" RepeatColumns="5" CellPadding="2" CellSpacing="2">
<asp:ListItem Value="role1" >Role1</asp:ListItem>
<asp:ListItem Value="role2">Role2 </asp:ListItem>
<asp:ListItem Value="role3" >Role3 </asp:ListItem>
<asp:ListItem Value="Role4">role4 </asp:ListItem>
<asp:ListItem Value="none" Selected="True">N/A </asp:ListItem>
</asp:RadioButtonList>
</div>
</div>
</itemtemplate>
<FooterTemplate>
</div>
</FooterTemplate>
</asp:Repeater>
</itemtemplate>
</asp:Repeater>
<asp:Button ID="btnSubmit" runat="server" Text="Submit" CssClass="buttonM bBlue" OnClientClick="btnSubmit_Click" /> <asp:Button ID="btnCancel" runat="server" Text="Cancel" CssClass="buttonM bBlue" OnClientClick="btnCancel_Click"/>
The submit button is outside the repeater but in the same form
Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSubmit.Click
For Each Item As RepeaterItem In rptrDivision.Items
If (Item.ItemType = ListItemType.Item) Or (Item.ItemType = ListItemType.AlternatingItem) Then
DivLabel = CType(Item.FindControl("lblDivName"), Label)
DivName = DivLabel.Text
DivMgr = CType(Item.FindControl("cbxDivMgr"), CheckBox)
'''do some logic
End If
Next
End Sub
I've looked in the debugger and item has the correct number of controls so I know I am in the right place, but the findcontrol in the repeater item can't locate the control by name. It always comes back as null.
Every example I can find from here to MSDN forums to asp.net to bytes.com show looping through the items in the repeater and calling the find control the same way. I can't figure out what I am doing wrong.
Edit:
SO here is the kicker just make sure I'm not crazy I did a loop through the controlscollection on the repeater item and on the second control it comes back with the ID "lblDivName" yet if I call the item.findControl("lblDivName") it returns a null value.
Control events (like a Button's click event) occur before DataBound events (see ASP.NET Page Life Cycle on MSDN for more information). Thus, your Repeater is not DataBound yet, so its databound controls have not been initialized (they are null).
You have some options.
Preferably, you would use the Repeater's databound event to work with it's data items - since this is when you know for sure that they are initialized and populated with values.
However, you could just call "DataBind" prior to doing the processing in your Click event:
Protected Sub btnSubmit_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnSubmit.Click
rptrDivision.DataSource = yourDataSource
rptrDivision.DataBind()
For Each Item As RepeaterItem In rptrDivision.Items
' The rest of your code
End Sub
This should ensure that your controls have values.

Create LinkButtons with dynamic ID's

I've dabbled in the past with VB and ASP classic and am currently trying to write my first site in ASP.net and I'm very much learning as I go...but I've spent all of today trying to do this one and I've not got anywhere with the usual googling.
Hopefully it's apparent in my code that I am trying to dynamically add 2 LinkButtons with unique ID's below a LinkButton with a static ID. I want the IDs in the 2 unique LinkButtons to have the "companyname" dataitem value in it so that I can unhide them when the first "companylink" is clicked - I'm yet to write the sub "LoadCompany" to unhide the two LinkButton's but I'm pretty confident I already know how to do that.
<asp:Content ContentPlaceHolderID="leftsidebarcontent" runat="server">
<li id="leftsidebarhead" class="sidebaritems">/* MENU */</li><br />
<asp:Datalist id="customers" runat="server" RepeatLayout="Flow">
<ItemTemplate>
<li class="leftsidebaritem sidebaritems"><asp:LinkButton id="CompanyLink" runat="server" OnCommand="LoadCompany" Text='<%#Container.DataItem("companyname")%>'></asp:LinkButton></li>
<li class="leftsidebaritem sidebaritems"><asp:LinkButton id='<%#Container.DataItem("companyname")%> & "Reviews"' runat="server" Text="Reviews"></asp:LinkButton></li>
<li class="leftsidebaritem sidebaritems"><asp:LinkButton id='LinkButton1' runat="server" Text="Other"></asp:LinkButton></li>
<br />
</ItemTemplate>
</asp:Datalist>
If it helps - the first LinkButton is to populate a nav menu down the left of the page, below each one of these LinkButton's I want two further linkbuttons which will be hidden, until the original linkbutton is clicked, at which point they unhide - so creating a kind of nested navigation menu.
You can do like this in markup:
<asp:Content ID="Content1" ContentPlaceHolderID="leftsidebarcontent" runat="server">
<p id="leftsidebarhead" class="sidebaritems">/* MENU */</p>
<br />
<asp:DataList ID="customers" runat="server" RepeatLayout="Flow" OnItemCommand="customers_ItemCommand" >
<ItemTemplate>
<li class="leftsidebaritem sidebaritems">
<asp:LinkButton ID="CompanyLink" runat="server" CommandName="LoadCompany"
Text='<%#DataBinder.Eval(Container.DataItem, "companyname")%>'></asp:LinkButton></li>
<ul id="ulSubItems" runat="server" visible="false">
<li class="leftsidebaritem sidebaritems">
<asp:LinkButton ID='LinkButton1' runat="server" Text="Reviews"></asp:LinkButton></li>
<li class="leftsidebaritem sidebaritems">
<asp:LinkButton ID='LinkButton2' runat="server" Text="Other"></asp:LinkButton></li>
</ul>
<br />
</ItemTemplate>
</asp:DataList>
</asp:Content>
And in the codebehind:
Protected Sub customers_ItemCommand(source As Object, e As DataListCommandEventArgs) Handles customers.ItemCommand
'Hide all subitems
For Each itm As DataListItem In customers.Items
If itm.ItemType = ListItemType.Item OrElse itm.ItemType = ListItemType.AlternatingItem Then
Dim ulSubItems As HtmlGenericControl = CType(itm.FindControl("ulSubItems"), HtmlGenericControl)
ulSubItems.Visible = False
End If
Next
If e.CommandName = "LoadCompany" Then
Dim MySubItems As HtmlGenericControl = CType(e.Item.FindControl("ulSubItems"), HtmlGenericControl)
If Not MySubItems Is Nothing Then
MySubItems.Visible = True
End If
End If
End Sub

Finding a Div or placeholder in a repeater control, and adding controls to it

I'm having trouble with a certain scenario. I have a repeater control, within I have a placeholder (and for the sake of testing, I've placed a div and tried that as well). I would like to, in my code behind page, find that placeholder or div, and put controls in it (for now, 3 textboxes and 2 buttons)
I have no issue with adding controls to a placeholder, I understand how that works, what I can't get here, is how to find this dynamic control here.
Here is some code snippets to help illustrate what I'm trying to do.
(the asp)
<asp:Repeater id="rptSpecialNotes" runat="server">
<ItemTemplate>
<asp:UpdatePanel ID="udpSpecialNotesRepeater" runat="server">
<ContentTemplate>
<asp:PlaceHolder ID="plhSpecialNotesRepeater" runat="server">
</asp:PlaceHolder>
</ContentTemplate>
</asp:UpdatePanel>
<p><%# eval("subject") %></p>
<div id="specialNotes" runat="server"></div>
<asp:imagebutton runat="server" AlternateText="add Motion" ImageUrl="images/controls/Exclaim.png" width="40" height="40"></asp:imagebutton>
<asp:imagebutton runat="server" AlternateText="add document" ImageUrl="images/controls/Documents.png" width="40" height="40"></asp:imagebutton>
<asp:imagebutton runat="server" AlternateText="move up" ImageUrl="images/controls/Arrow-Up.png" width="40" height="40" CommandName="moveUp" CommandArgument='<%# Container.ItemIndex & "," & eval("ItemID") %>'></asp:imagebutton>
<asp:imagebutton runat="server" AlternateText="move down" ImageUrl="images/controls/Arrow-Down.png" width="40" height="40" CommandName="moveDown" CommandArgument='<%# Container.ItemIndex & "," & eval("ItemID") %>'></asp:imagebutton>
<asp:imagebutton runat="server" AlternateText="delete" ImageUrl="images/controls/Delete.png" width="40" height="40" CommandName="delete" CommandArgument='<%# Container.ItemIndex & "," & eval("ItemID") %>'></asp:imagebutton>
<asp:imagebutton runat="server" AlternateText="edit" ImageUrl="images/controls/Globe.png" width="40" height="40" CommandName="edit" CommandArgument='<%# Container.ItemIndex & "," & eval("ItemID") %>'></asp:imagebutton>
</ItemTemplate>
</asp:Repeater>
The image button edit, hits the rptSpecialNotes_Item command, which calls a method (edit special notes) which looks something like this
Dim commandArguments() As String = Split(e.CommandArgument, ",")
Dim divId As String = commandArguments(0)
Dim itemId As String = commandArguments(1)
'determine action based on command name
If e.CommandName = "edit" Then
Call editSpecialNotes(itemId,divId)
End If
and edit special notes is to place things in the given divID. For the sake of getting this to work, I've given divID a static value that I know exists (rptSpecialNotes_plhSpecialNotesRepeater_1) or something similar to that extent. However, I always end up with a null object reference.
Use FindControl to get the nested control in the rptSpecialNotes_Item event handler - this will return the control:
sender.FindControl("specialNotes")
It will return a Control type, so a cast is needed to the right type if you want to use the specific properties and methods of that type.
I'm not sure, but maybe this helps:
<asp:imagebutton runat="server" AlternateText="edit" ImageUrl="images/controls/Globe.png" width="40" height="40" CommandName="edit" CommandArgument='<%# Container.ClientID & "," & eval("ItemID") %>'></asp:imagebutton>
also, for FindControl method, in ItemDataBound event;
Dim plh As PlaceHolder = e.Item.FindControl("YOURCONTROLID")
In the rptSpecialNotes_Item command event handler:
Dim plh As PlaceHolder = CType(e.Item.FindControl("plhSpecialNotesRepeater"), PlaceHolder)
plh.Controls.Add(lbl)

Handling a DropDownList in a Nested ListView

I have two nested .net ListViews. I need to filter the contents of the inner listview by selecting from a dropdown list in the outer listview. The layout of the control is like this:
<asp:listview id="lvOuter" runat="server" onitemdatabound="lvOuter_OnItemDataBound"
onitemcommand="lvOuter_OnItemCommand" onitemcreated="lvOuter_ItemCreated" onselectedindexchanged="lvOuter_SelectedIndexChanged">
<layouttemplate>
<ul>
<asp:placeholder id="itemPlaceholder" runat="server" />
</ul>
</layouttemplate>
<itemtemplate>
<asp:dropdownlist id="ddlTest" runat="server" onselectedindexchanged="ddlTerm_SelectedIndexChanged" autopostback="true" >
<asp:listitem text="6" value="6"/>
<asp:listitem text="9" value="9"/>
</asp:dropdownlist>
<asp:listview id="lvInner" runat="server" onselectedindexchanging="lvInner_SelectedIndexChanging"
onitemdatabound="lvInner_ItemDataBound" onitemcommand="lvInner_OnItemCommand">
<layouttemplate>
<asp:placeholder id="itemPlaceholder" runat="server" />
</layouttemplate>
<itemtemplate>
<!--Results displayed here-->
</itemtemplate>
</asp:listview>
</itemtemplate>
</asp:listview>
On the page load I bind data to the outer listview and on OnItemDataBound I bind the inner listview. This is all working fine, but what I need to do now is to re-bind the inner listview with a new query that includes the parameter from the drop down list. This should happen when the user selects a new value in the drop downlist. (OnSelectedIndexChanged) I can access the value easily enough through the sender, as so:
protected void ddlMyDropDown_OnSelectedIndexChanged(object sender, EventArgs e)
{
DropDownList ddlMyDropDown = sender as DropDownList;
string value = ddlMyDropDown.SelectedValue;
}
but I'm unable to then find the inner listview relating to that dropdown in order to bind the results of the new query with the added where clause. I'm sure this must be a pretty common requirement. Any pointers would be greatly appreciated.
Have you tried using something like <%# Eval("value", "{0}") %> as seen here
I seem to recall doing something akin to yours with this. It has been awhile since I have done this so sorry if this is not accurate.

Resources