fetching values from the repeater control in ItemDataBound event - asp.net

how to fetch values of repeater control in the ItemDataBound event
i wrote the following asp code
<asp:Repeater ID="repeaterItems" runat="server" OnItemDataBound="rptData_ItemDataBound" >
<itemtemplate>
<tr>
<td style="font-family:Tahoma; font-size:small"><asp:Label id="content" runat="server"> <%#DataBinder.Eval(Container.DataItem, "cont")%></asp:Label></td>
</tr>
<tr><td style="font-family:Verdana; font-size:small"><asp:Label id="url" runat="server"><a style="color:Green" href="<%#DataBinder.Eval(Container.DataItem, "url")%>" target="_blank"><%#DataBinder.Eval(Container.DataItem, "url")%></a></asp:Label></td></tr>
<tr><td><asp:LinkButton runat="server" ID="glossary" >Glossary</asp:LinkButton></td></tr>
<tr><td><asp:HiddenField runat="server" ID="id1"/><%#DataBinder.Eval(Container.DataItem, "id")%></td></tr>
<tr><td></td></tr><tr><td></td></tr><tr><td></td></tr>
</itemtemplate>
</asp:Repeater>
and the ItemDataBound event in vb.net
Protected Sub rptData_ItemDataBound(ByVal source As Object, ByVal e As RepeaterItemEventArgs)
Dim content As String = ""
Dim url As String = ""
Dim lbl1 As Label = TryCast(e.Item.FindControl("content"), Label)
Dim lbl2 As Label = TryCast(e.Item.FindControl("url"), Label)
content = lbl1.Text
url = lbl2.Text
Dim btn As LinkButton = CType(e.Item.FindControl("glossary"), LinkButton)
btn.PostBackUrl = "glossary.aspx?cont=" + content + "&url=" + url
end sub
but i get empty value in content and url...
please help

First of all in markup use Text property of label, do not put databinder.Eval in
<asp:Label ..> do not put content here </asp:Label>
In item databound event first find out control in which template.
follow this example :
Markup:
<asp:Repeater ID="Repeater1" runat="server"
onitemdatabound="Repeater1_ItemDataBound">
<HeaderTemplate>
</HeaderTemplate>
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval("content") %>'></asp:Label>
<asp:LinkButton ID="LinkButton1" runat="server">LinkButton</asp:LinkButton>
</ItemTemplate>
<AlternatingItemTemplate></AlternatingItemTemplate>
<SeparatorTemplate></SeparatorTemplate>
</asp:Repeater>
Source Code :
C#:
protected void Repeater1_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item)
{
Label lbl = (Label)e.Item.FindControl("Label1");
LinkButton link = (LinkButton)e.Item.FindControl("LinkButton1");
link.PostBackUrl = "abcd/" + lbl.Text;
}
}
VB.Net:
Protected Sub Repeater1_ItemDataBound(sender As Object, e As RepeaterItemEventArgs)
If e.Item.ItemType = ListItemType.Item Then
Dim lbl As Label = DirectCast(e.Item.FindControl("Label1"), Label)
Dim link As LinkButton = DirectCast(e.Item.FindControl("LinkButton1"), LinkButton)
link.PostBackUrl = "abcd/" + lbl.Text
End If
End Sub

Related

Unable to read the text from a TextBox` within a `Repeater`

I am not getting any errors but I am unable to get the value from a TextBox.
This is my VB code for reading the TextBox value:
Private Sub btn_Save_Click(sender As Object, e As EventArgs) Handlesbtn_Save.Click
For Each item As RepeaterItem In Article_Block_Migrated.Items
Dim txtField As Label = item.FindControl("Article_Number")
Dim a = txtField.Text
Dim txtField1 As TextBox = DirectCast(item.FindControl("txt_DWPDate"), TextBox)
Dim b = txtField1.Text
Next
End Sub
This is my ASP code for the Repeater:
<asp:Repeater ID="Article_Block_Migrated" runat="server">
<ItemTemplate>
<asp:TextBox Width="80px" ID="txt_DWPDate" runat="server" MaxLength="50"></asp:TextBox>
</ItemTemplate>
</asp:Repeater>

I can't access the ID nested inside the ListView <itemtemplate>

I am trying to grab the value of the checkbox every time a user checks it using the following markup:
<!---- <asp:CheckBoxList ID="CheckboxWattage" runat="server" RepeatColumns="1" CellSpacing="-1" RepeatDirection="Vertical" RepeatLayout="Flow" TextAlign="Right" Width="300px">
<asp:ListItem text="" value=""></asp:ListItem>
</asp:CheckBoxList>--->
<asp:Listview id="filterListView" runat="server" DataSourceID="" onitemdatabound="filterListView_ItemDataBound" >
<ItemTemplate>
<asp:CheckBox ID="CheckBox1" value='<%#DataBinder.Eval(Container.DataItem,"UDF_WATTAGE") %>' runat="server"/>
<asp:label ID="LabelValue" AssociatedControlID="CheckBox1" runat="server" text='<%#Eval("UDF_WATTAGE") %>' ></asp:label>
<asp:label Style="font-size:12px; font-style: italic;" ID="countLabel" runat="server" text='<%# "(" + DataBinder.Eval(Container.DataItem,"CountofUDF_WATTAGE") +")" %>' ></asp:label>
</br>
</ItemTemplate>
</asp:Listview>
<asp:Button id="wattagebtn" text="Apply" class="btn btn-danger" style="float:right;" onclick="wattageApply_Click" runat="server"></asp:Button>
<asp:Label ID="Label1" runat="server" Text="hi"></asp:Label>
</div>
</div>
code behind update! I think I was able to grab the CheckBox1 ID. how can I grab the checkbox value? When checked?
I will update once I find the solution for anyone that's having the same issue.
UPDATEEE FOUND THE SOLUTION. i had to put if(!IsPostBack){ }
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
dapter.Fill(ds);
filterListView.DataSource = ds;
filterListView.DataBind();
}
protected void filterListView_ItemDataBound(object sender, ListViewItemEventArgs e)
{
if (e.Item.ItemType == ListViewItemType.DataItem)
{
}
}
protected void wattageApply_Click(Object sender, System.EventArgs e)
{
foreach (ListViewItem item in filterListView.Items)
{
CheckBox cb = item.FindControl("CheckBox1") as CheckBox;
if (cb.Checked == true)
{
string ch;
Label1.Text = cb.Text;
}
else
{
Label2.Text = cb.Text;
}
}
<asp:ListView ID="ListView1" runat="server" DataSourceID="">
<ItemTemplate>
<div>
<asp:CheckBox ID="CheckBox1" runat="server"
OnCheckedChanged="ListViewItemCheckChanged"
Text='<%#DataBinder.Eval(Container.DataItem,"UDF_WATTAGE") %>' />
.
.
.
</div>
</ItemTemplate>
</asp:ListView>
Code Behind (VB.NET):
Protected Sub ListViewItemCheckChanged(sender As Object, e As EventArgs)
Dim cb As CheckBox = sender
// at this point the variable cb contains the user selected checkbox
End Sub
This will allow you to examine the last Checkbox the user clicked
Keep in mind there will be a postback on each click.
This will give you what you are asking for but is probably not the best interface experience for the user.
Typically when presented with multiple check boxes you allow all the user selections and then process the selections with one postback via some submit style button. This would require:
Looping through the ListView's Item Collection,
For each ListViewDataItem find each CheckBox via FindControl("CheckBox1")
Check for CheckBox1.Checked() and act accordingly
Addendum: How to Loop through ListView Items (VB.NET):
Private Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
Dim cb As CheckBox
For Each lvi As ListViewDataItem In ListView1.Items
cb = lvi.FindControl("CheckBox1")
If cb.Checked Then
...
Else
...
End If
Next
End Sub
Addendum: A word about Checkboxes:
An ASP CheckBox doesn't have a value per se. It's "value" is the Boolean "cb.Checked". But there are two ways you can associate a value with CheckBox
1) If the value is not a security issue and not particulary lengthy you can add an Attribute in the ListView ItemDataBound event
Private Sub ListView1_ItemDataBound(sender As Object, e As ListViewItemEventArgs) Handles ListView1.ItemDataBound
If e.Item.ItemType = ListViewItemType.DataItem Then
Dim drv As DataRowView = e.Item.DataItem
Dim cb As CheckBox = e.Item.FindControl("CheckBox1")
cb.Attributes("some-legal-html-attribute-name") = drv("Some_dataset_field")
End If
End Sub
You are doing something similar with this in your aspx:
<asp:CheckBox ID="CheckBox1" runat="server"
value='<%#DataBinder.Eval(Container.DataItem,"UDF_WATTAGE") %>'/>
the above should render to something like this:
<input id="ListviewMangledprefix_CheckBox1" type="checkbox"
value="[value of UDF_WATTAGE FIELD]" />
Inspect the field in the rendered browser page and see if the "value" attribute is being rendered. If so you should be able to access it in the code behind as:
Dim wattage as String = cb.Attributes("value")
2) Better and more secure would be to implement and use ListView1.DataKeys. But this is a much more extensive topic that you should research when you have time

how to make a label in a nested repeater visible programmatically

I have two repeaters, one nested in the other. I'm outputting a list of course titles in the parent repeater and the dates of those courses in the child repeater. This part is working fine. But, not all the course titles necessarily have dates available at any given time, so I want to be able to put a message up under each Course title that currently has no dates saying to check back regularly, blah, blah, blah. I've put the label in the footer template of the nested repeater with visibility=false and am trying to set the visibility=true at the appropriate time in the ItemDataBound Sub. Unfortunately, this is not working. I'm not getting any errors, the label just isn't showing up. I'm really hoping someone can help me out with my code or suggest an alternate way to do this. I'm kinda new to asp.net(VB) and am still struggling a bit. I've never tried nesting repeaters before. Here is my code:
.aspx
<asp:Repeater ID="rptTech" runat="server" >
<HeaderTemplate>
<table class="tableCourses">
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<strong><asp:Label runat="server" ID="lblCourseName" Text='<%# Eval("CourseName") %>'></asp:Label></strong>
<br />
<asp:Label runat="server" ID="lblCourseSummary" Text='<%# Eval("Summary") %>'></asp:Label>
<br />
<asp:HyperLink ID="hpCourseMaterial" Visible='<%# CheckCourseMaterial(Eval("CourseMaterial")) %>' NavigateUrl='<%# "/files/Portal_Course_Material/" & Eval("CourseMaterial")%>' Text="Download Course Material" runat="server"></asp:HyperLink>
</td>
</tr>
<tr>
<td>
<asp:Repeater ID="rptTechDates" DataSource='<%#Eval("relCourses") %>' runat="server" >
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<strong><asp:Label runat="server" ID="lblDate" Text='<%# CDate(Eval("dteDate")).ToString("dd/MM/yyyy") %>'></asp:Label></strong><br />
<asp:Label runat="server" ID="dteTime" Text='<%# "Time: " & CDate(Eval("dteTime2")).ToString("HH:mm") & " EST" %>'></asp:Label><br />
<asp:HyperLink ID="Register" NavigateUrl='<%# "/Test.aspx?intMeetingID2=" & Eval("pkWebinarID")%>' Text="Register" runat="server"></asp:HyperLink>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
<tr>
<td>
<asp:Label ID="lblNoCourses" Text="There are no course dates available at this time. Please check back regularly to see any updates." runat="server" Visible="False"></asp:Label>
</td>
</tr>
</table>
</FooterTemplate>
</asp:Repeater>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
And Codebehind:
Protected Sub Page_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
Dim curDate As Date = CDate(Now)
'Create the connection
Dim connstring As String
connstring = ConfigurationManager.ConnectionStrings("LPISQLConn").ConnectionString
Using conn As New SqlConnection(connstring)
Dim cmd As New SqlCommand("SELECT foo1, foo2, foo3 FROM tblFoo", conn)
cmd.CommandType = CommandType.Text
Dim ad As New SqlDataAdapter(cmd)
Dim ds As New DataSet()
ad.Fill(ds)
ds.Relations.Add(New DataRelation("relCourses", ds.Tables(0).Columns("fkcrsID"), ds.Tables(1).Columns("webinarID"), False))
rptTech.DataSource = ds.Tables(0)
rptTech.DataBind()
End Using
End Sub
Protected Sub rptTech_ItemDataBound(ByVal sender As Object, ByVal e As RepeaterItemEventArgs)
If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then
Dim drv As DataRowView = TryCast(e.Item.DataItem, DataRowView)
Dim rptTechDates As Repeater = TryCast(e.Item.FindControl("rptTechDates"), Repeater)
rptTechDates.DataSource = drv.CreateChildView("relCourses")
If rptTechDates.Items.Count < 1 And rptTechDates IsNot Nothing Then
If e.Item.ItemType = ListItemType.Footer Then
Dim lblNoCourses As Label = TryCast(e.Item.FindControl("lblNoCourses"), Label)
If lblNoCourses IsNot Nothing Then
lblNoCourses.Visible = True
End If
End If
Else
rptTechDates.DataBind()
End If
End If
End Sub
I would do the following:
Change your ItemDataBoundEvent for the parent repeater to:
Protected Sub rptTech_ItemDataBound(ByVal sender As Object, ByVal e As RepeaterItemEventArgs)
If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then
Dim drv As DataRowView = TryCast(e.Item.DataItem, DataRowView)
Dim rptTechDates As Repeater = TryCast(e.Item.FindControl("rptTechDates"), Repeater)
rptTechDates.DataSource = drv.CreateChildView("relCourses")
rptTechDates.DataBind()
End If
End Sub
Add this to the markup of your child repeater:
OnItemDataBound="rptTechDates_ItemDataBound"
Now add this:
Protected Sub rptTechDates_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs)
If e.Item.ItemType = ListItemType.Footer Then
If DirectCast(DirectCast(e.Item.NamingContainer, Repeater).DataSource, DataTable).Rows.Count = 0 Then
DirectCast(e.Item.FindControl("lblNoCourses"), Label).Visible = True
End If
End If
So, if the number of rows in the child repeater's datasource is 0, then show the label.
EDIT After comment from OP
Protected Sub rptTechDates_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs)
If e.Item.ItemType = ListItemType.Footer Then
If DirectCast(DirectCast(e.Item.NamingContainer, Repeater).DataSource, DataView).Count = 0 Then
DirectCast(e.Item.FindControl("lblNoCourses"), Label).Visible = True
End If
End If
You want to search rptTechDates repeater for the lblNoCourses control. The e.Item.FindControl("lblNoCourses") is searching the rptTech repeater which doesn't exist. See this question to search the control in the rptTechDates footer.
Also, you'll want to call Databind() on the repeater after setting it's DataSource
rptTechDates.DataSource = drv.CreateChildView("relCourses")
rptTechDates.Databind()

Accessing Controls Inside ASP.NET View Controls (Event Handling)

If I have the following ListView, how can I attach a SelectedIndexChanged event listener to the DropDownList so I can perform a command on the respective object? Imagine I have a list of new users and I want to add them to a usergroup by selecting the group from the DropDownList.
<asp:ListView ID="NewUsers" runat="server" DataSourceID="NewUsersSDS" DataKeyNames="ID">
<LayoutTemplate>
<asp:Table ID="groupPlaceholder" runat="server"><asp:TableRow></asp:TableRow></asp:Table>
</LayoutTemplate>
<GroupTemplate>
<asp:TableCell ID="itemPlaceholder" runat="server"></asp:TableCell>
</GroupTemplate>
<ItemTemplate>
<asp:Table ID="NewUsersTable" runat="server" Width="32%" CssClass="inlineTable">
<asp:TableRow>
<asp:TableCell Width="100px"><%# Eval("FullName").ToString.Trim()%></asp:TableCell>
<asp:TableCell>
<asp:HiddenField ID="RowIndex" runat="server" Value="<%# Container.DisplayIndex %>" />
<asp:DropDownList ID="UserGroupSelect" runat="server" DataSourceID="UserGroupSelectSDS" DataValueField="ID" DataTextField="UserGroup"
OnSelectedIndexChanged="UserGroupSelect_SelectedIndexChanged" AutoPostBack="True">
</asp:DropDownList>
</asp:TableCell>
</asp:TableRow>
</asp:Table>
</ItemTemplate>
</asp:ListView>
I've been having issues accessing controls inside of __View controls. I read in a few places that you could access them by NewUsers.FindControl([ControlID as String]) but this doesn't seem to be working for me. I guess this is what's called a dynamic control? Not really sure, feeling a bit lost.
As always, your help is greatly appreciated. ;)
Additional Info / Code
'Now working code, thanks to James :)
Protected Sub ItemBind(ByVal sender As Object, ByVal e As ListViewItemEventArgs) Handles NewUsers.ItemDataBound
Dim lv As ListView = DirectCast(sender, ListView)
If e.Item.ItemType = ListViewItemType.DataItem Then
lv.DataKeys(e.Item.DataItemIndex).Value.ToString() 'get the datakey
End If
End Sub
Protected Sub UserGroupSelect_SelectedIndexChanged(ByVal sender As Object, ByVal e As EventArgs)
Dim RowIndex As Integer = CInt(DirectCast(DirectCast(sender, DropDownList).Parent.FindControl("RowIndex"), HiddenField).Value)
Dim pk As Integer = CInt(NewUsers.DataKeys(RowIndex)("ID"))
Try
MessageBox("Update key " + pk.ToString, "Update Key") 'Custom js "alert" box function
Catch ex As Exception
MessageBox("Something went wrong, is the update key empty?")
End Try
End Sub
To access controls in a ListView (or any databound control), you need to use FindControl on the item/row:
ListViewItem item = ListView1.Items[0];
if (item != null)
{
DropDownList ddl = item.FindControl("DropDownList1") as DropDownList;
if (ddl != null)
{
string value = ddl.SelectedValue;
}
}
As for attaching a SelectedIndexChanged event, you can do it like this:
<ItemTemplate>
<asp:DropDownList ID="DropDownList1" runat="server"
AutoPostBack="true"
OnSelectedIndexChanged="DropDownList1_SelectedIndexChanged">
</asp:DropDownList>
<asp:HiddenField ID="HiddenField1" runat="server" Value='<%# Container.DisplayIndex %>' />
</ItemTemplate>
Code-behind:
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
int rowIndex = Convert.ToInt32(((HiddenField)((DropDownList)sender).Parent.FindControl("HiddenField1")).Value);
ListViewItem item = ListView1.Items[rowIndex];
if (item != null)
{
//your logic here
}
}
To retrieve a datakey:
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
int rowIndex = Convert.ToInt32(((HiddenField)((DropDownList)sender).Parent.FindControl("HiddenField1")).Value);
int pk = (int)ListView1.DataKeys[rowIndex]["PrimaryKey"];
}

Repeater control. Using a table that spans rows

The following "FindControl" method fails to find the imgAd control. Any idea why? Could it be the Table that contains it? The intent of the table is to line things up in columns across rows.
<asp:Content ID="Content3" ContentPlaceHolderID="phPageContent" runat="Server">
<asp:Repeater ID="repBanner" runat="server">
<HeaderTemplate>
<table>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<asp:Image ID="imgAd" runat="server" AlternateText="Panda Visa" ImageUrl="Images/AffiliateBanners/125%20by%20125.jpg" />
</td>
<td>
<asp:TextBox ID="txtHtml" runat="server" Columns="80" ReadOnly="True" Rows="7" TextMode="MultiLine"></asp:TextBox>
</td>
<td>
<asp:Button runat="server" Text="Copy HTML to Clipboard" OnClientClick="ClipBoard('txtHtml')" />
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
Protected Sub repBanner_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles repBanner.ItemDataBound
Dim CurrentAd As Ad = CType(e.Item.DataItem, Ad)
Dim RepeaterItem As RepeaterItem = e.Item
Dim imgAd As Image = CType(RepeaterItem.FindControl("imgAd"), Image)
imgAd.ImageUrl = "Images/" & "125 by 125.jpg" '<<<Error occurs here
End Sub
Object reference not set to an instance of an object.
Here's some debug info that I thought may help:
? RepeaterItem.Controls.Count
1
? RepeaterItem.Controls(0).Controls.Count
0
? typename(RepeaterItem.Controls(0))
"LiteralControl"
You need to check e.Item.ItemType to make sure that you're dealing with an item, not a header or footer. Something like this:
Protected Sub repBanner_ItemDataBound(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.RepeaterItemEventArgs) Handles repBanner.ItemDataBound
If (e.Item.ItemType <> ListItemType.Item AndAlso e.Item.ItemType <> ListItemType.AlternatingItem) Then
Return
End If
Dim CurrentAd As Ad = CType(e.Item.DataItem, Ad)
Dim RepeaterItem As RepeaterItem = e.Item
Dim imgAd As Image = CType(RepeaterItem.FindControl("imgAd"), Image)
imgAd.ImageUrl = "Images/" & "125 by 125.jpg" '<<<Error occurs here
End Sub

Resources