Can't find control within asp.net repeater? - c#

I have the following repeater below and I am trying to find lblA in code behind and it fails. Below the markup are the attempts I have made:
<asp:Repeater ID="rptDetails" runat="server">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td><strong>A:</strong></td>
<td><asp:Label ID="lblA" runat="server"></asp:Label>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
First I tried,
Label lblA = (Label)rptDetails.FindControl("lblA");
but lblA was null
Then I tried,
Label lblA = (Label)rptDetails.Items[0].FindControl("lblA");
but Items was 0 even though m repeater contains 1 itemtemplate

You need to set the attribute OnItemDataBound="myFunction"
And then in your code do the following
void myFunction(object sender, RepeaterItemEventArgs e)
{
Label lblA = (Label)e.Item.FindControl("lblA");
}
Incidentally you can use this exact same approach for nested repeaters. IE:
<asp:Repeater ID="outerRepeater" runat="server" OnItemDataBound="outerFunction">
<ItemTemplate>
<asp:Repeater ID="innerRepeater" runat="server" OnItemDataBound="innerFunction">
<ItemTemplate><asp:Label ID="myLabel" runat="server" /></ItemTemplate>
</asp:Repeater>
</ItemTemplate>
</asp:Repeater>
And then in your code:
void outerFunction(object sender, RepeaterItemEventArgs e)
{
Repeater innerRepeater = (Repeater)e.Item.FindControl("innerRepeater");
innerRepeater.DataSource = ... // Some data source
innerRepeater.DataBind();
}
void innerFunction(object sender, RepeaterItemEventArgs e)
{
Label myLabel = (Label)e.Item.FindControl("myLabel");
}
All too often I see people manually binding items on an inner repeater and they don't realize how difficult they're making things for themselves.

I just had the same problem.
We are missing the item type while looping in the items. The very first item in the repeater is the header, and header does not have the asp elements we are looking for.
Try this:
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{Label lblA = (Label)rptDetails.Items[0].FindControl("lblA");}

Code for VB.net
Protected Sub rptDetails_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles rptDetails.ItemDataBound
If e.Item.ItemType = ListItemType.AlternatingItem Or e.Item.ItemType = ListItemType.Item Then
Dim lblA As Label = CType(e.Item.FindControl("lblA"), Label)
lblA.Text = "Found it!"
End If
End Sub

Investigate the Repeater.ItemDataBound Event.

You should bind first.
for example)
rptDetails.DataSource = dataSet.Tables["Order"];
rptDetails.DataBind();

Related

Nested repeater will not display bound information from list

I am trying to get a page to display information in a row layout using repeaters. I have one working that allows me to dynamically create hyperlinks, however i cant get my nested repeater to work to display the date the file was created. Is it possible to use repeaters to dynamically display multiple variables from lists as i'm trying to do below?
.aspx
<asp:Repeater id="repLinks" runat="server">
<ItemTemplate>
<tr><td>
<asp:HyperLink runat="server" NavigateUrl='<%# Container.DataItem.ToString() %>' Text="<%# Container.DataItem.ToString().Split('\\').Last() %>" />
<td>
<asp:Repeater ID="Repeater2" runat="server" OnItemDataBound="Repeater2_ItemDataBound" >
<ItemTemplate>
<%# Container.DataItem.ToString()%>
</ItemTemplate>
</asp:Repeater>
</td>
<td>
Submitted By <!--add repeater-->
</td>
<td>
Mark as Billed <!--add repeater-->
</td>
</td></tr>
</ItemTemplate>
</asp:Repeater>
.aspx.cs
public List<string> CD = new List<string>();
protected void Page_Load(object sender, EventArgs e)
{
//Welcomes User
string Uname = Environment.UserName;
UserName.Font.Size = 17;
UserName.Text = "Welcome: " + Uname;
//gives path and constructs lists for directory paths and file links
string root = "C:\\Users\\James\\Documents\\Visual Studio 2015\\WebSites";
List<string> lLinks = new List<string>();
//adds files to list
foreach (var path in Directory.GetDirectories(#root))
{
foreach (var path2 in Directory.GetFiles(path))
{
lLinks.Add(path2);
CD.Add(File.GetCreationTime(path2).Date.ToString("yyyy-mm-dd"));
}
}
//Define your list contents here
repLinks.DataSource = lLinks;
repLinks.DataBind();
}
protected void Repeater2_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
Repeater Repeater2 = (Repeater)(e.Item.FindControl("Repeater2"));
Repeater2.DataSource = CD;
Repeater2.DataBind();
}
}
The issue with your code is that you are binding the nested repeater control (Repeater2) in the ItemDataBound event of Repeater2 repeater itself which will never get fired because ItemDataBound event is fired for each item in collection when it is bounded to the repeater control.
You should write the logic in ItemDataBound event of your parent repeater like this:-
<asp:Repeater id="repLinks" runat="server" OnItemDataBound="Repeater1_ItemDataBound">
Then, write the logic in this event handler:-
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
Repeater Repeater2 = (Repeater)(e.Item.FindControl("Repeater2"));
Repeater2.DataSource = CD;
Repeater2.DataBind();
}
}
Also, In the Page_Load event you should bind the Parent Repeater Repeater1 on just the initial page load so wrap it inside !IsPostBack and populate your datasource lLinks & CD from a separate method intead of doing it in Page_Load event.

Items are looping all items in Repeater's ItemDataBound event

I have a normal Repeater Control in my aspx page
<asp:Repeater ID="rpt1" runat="server" OnItemDataBound="rpt1_ItemDataBound">
<ItemTemplate>
<asp:CheckBox ID="chks" runat="server" />
<asp:TextBox ID="txtName" runat="server" CssClass="form-control" Text='<%# DataBinder.Eval(Container,"DataItem.Name").ToString()%>'></asp:TextBox><asp:Label ID="lblValue" runat="server" Visible="false" Text='<%# DataBinder.Eval(Container,"DataItem.Id").ToString() %>'></asp:Label>
</ItemTemplate>
</asp:Repeater>
On the button click I'm binding data to the Repeater as
rpt1.DataSource = GetData();
rpt1.DataBind();
After binding the ItemDataBound event is called. In that I'm looping through the repeater items for some manipulations
protected void rpt1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
foreach (RepeaterItem item in rpt1.Items)
{
if (item.ItemType == ListItemType.Item || item.ItemType == ListItemType.AlternatingItem)
{
string val = ((Label)item.FindControl("lblValue")).Text;
// Some Stuff
}
}
}
The problem is that the loop is getting started from first every time.
For Ex if my data is as 1 2 3 so on.....
It is iterarting as
1
1 2
1 2 3
How can I make it as
1
2
3
What am I doing wrong
ItemDataBound is already called for every item in the repeater, so you don't need a loop there.
protected void rpt1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
string val = ((Label)e.Item.FindControl("lblValue")).Text;
// Some Stuff
}
}
Side-Note: that applies to all Data-Bound Web Server Controls.

Give asp:hyperlink in a repeater a url from code behind

Okay so imagine next situation:
I have a .ascx file with a repeater and in this repeater there is a asp:hyperlink.
Is it possible to set the url of this hyperlink from the code behind?
In the end the link will always point towards the same url but it needs to be repeated x-times.
test code ascx:
<asp:Repeater runat="server" ID="repeater" OnItemDataBound="repeater_ItemDataBound">
<ItemTemplate>
<div class="container">
<asp:HyperLink ID="hypUrl" runat="server" Text="Dit is een test link"> </asp:HyperLink>
</div>
</ItemTemplate>
</asp:Repeater>
Normally in the code behind I would do something like:
hypUrl.NavigateUrl = Url;
But because the hyperlink is in a repeater it doesnt seem to find the ID.
Anyone knows what the best way is to achieve this?
Thanks in advance!
In repeater's ItemDataBound event. Do it like this
protected void repeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item ||
e.Item.ItemType == ListItemType.AlternatingItem)
{
HyperLink hypLink = (HyperLink)e.Item.FindControl("hypUrl");
hypLink.NavigateUrl = "http//www.stackoverflow.com";
}
}
Yes, in your repeater_ItemDataBound event:
protected void repeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
// Find the hyperlink
HyperLink hypUrl = (HyperLink)e.Item.FindControl("hypUrl");
// Set the property
hypUrl.NavigateUrl = "foo";
}
}

How to add web user controls to repeater

Scenario:
UsrControl: custom user control, which contains a textbox and a button, rederend horizontally (in one line).
UsrControlContainer: custom user control, which should be able to display multiple UsrControl objects (each object in seperate line, so the Seperator template will probably be <br />. This control also contains a button, which adds new UsrControl to the collection.
My code:
<asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click"/>
<asp:Repeater ID="rptExample" runat="server">
<ItemTemplate>
</ItemTemplate>
<SeparatorTemplate><br /></SeparatorTemplate>
</asp:Repeater>
And:
protected void Button1_Click(object sender, EventArgs e)
{
rptExample.DataSource = new List<UsrControl> {new UsrControl(), new UsrControl()};
rptExample.DataBind();
}
Simple question - what should I put in ItemTemplate to make this work?
Edit - I also want to pass some parameters to UsrControl before rendering it.
<asp:Repeater ID="rptExample" runat="server">
<ItemTemplate>
<uc:UsrControl runat="server" />
</ItemTemplate>
<SeparatorTemplate><br /></SeparatorTemplate>
</asp:Repeater>
protected void Button1_Click(object sender, EventArgs e)
{
rptExample.DataSource = Enumerable.Range(0, 2);
rptExample.DataBind();
}
Following your question in answer. You can catch every binding object in ItemDataBound event. So for example, as i used, set whole object as user control property.
protected void PersonesRepeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
PersonLine line = (PersonLine)e.Item.FindControl("Person1");
line.Person = e.Item.DataItem as Osoba;
}
}
Ofcourse, you have to add the event handler to your repeater:
<asp:Repeater runat="server" ID="PersonesRepeater" OnItemDataBound="PersonesRepeater_ItemDataBound"><ItemTemplate>
<my:Person ID="Person1" runat="server" />
</ItemTemplate>
</asp:Repeater>

Repeater which Event to use to find a control inside the repeater

I use asp.net and c#4.
I have a repeater within inside a HyperLink Control.
I need to Find the HyperLink Control and change some of its properties with some logic before rendering it on the page.
With my code here posted I get a null value for the control so I'm not able to get it.
Any idea what I'm doing wrong? Thanks for your time on this.
<asp:Repeater ID="RepeaterEditorsChoice" runat="server" DataSourceID="ObjectDataSourceEditorsChoice"
OnItemCreated="RepeaterEditorsChoice_ItemCreated" OnItemDataBound="RepeaterEditorsChoice_ItemDataBound">
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<asp:HyperLink ID="uxLink" runat="server"></asp:HyperLink>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
CODE BEHIND:
protected void RepeaterEditorsChoice_ItemCreated(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.AlternatingItem || e.Item.ItemType == ListItemType.Item)
{
HyperLink myLink = (HyperLink)((Repeater)sender).FindControl("uxLInk"); // ERROR: it is null
dynamic o = e.Item.DataItem;
if (o.TypeContent == "AR")
{
myLink.Text = #"'<%# Eval(\""Title\"") %>'";
myLink.NavigateUrl = #"'<%# GetRouteUrl(""ArticleDetails"", new {ContentId = Eval(""ContentId""), TitleUrl = Eval(""TitleUrl"")}) %>'";
}
if (o.TypeContent == "BP")
{
myLink.Text = #"'<%# Eval(\""Title\"") %>'";
myLink.NavigateUrl = #"'<%# GetRouteUrl(""BlogPostDetails"", new {ContentId = Eval(""ContentId""), TitleUrl = Eval(""TitleUrl"")}) %>'";
}
}
}
On item data bound
then just (YourClass)e.Item.FindControl("its name");

Categories