in a repeater, i want to do a function on every item bounded, example
<asp:Repeater runat="server" ID="rptArticleContent"
OnItemDataBound="rptArticleContent_ItemDataBound">
<ItemTemplate>
<tr>
<td width="365" valign="top" align="left" class="bodyContent" bgcolor="#FFFFFF">
<div>
<h2 class="h2">
<asp:Label runat="server" ID="dsds"> <%#Eval("Title") %></asp:Label>
</h2>
<div class="article-body">
<div class="Article-image">
<%#Eval("Image") %>
</div>
<%#Eval("Description") %>
</div>
<asp:Literal runat="server" ID="litArticleSource" Text='<%#Eval("Source") %>'>
</asp:Literal>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
in code behind i want to do some manipulation on the data inside the Literal
protected void rptArticleContent_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
Literal litArticleSource = rptArticleContent.FindControl
("litArticleSource") as Literal;
string ArticleSourcesR = litArticleSource.Text;
}
ArticleSourcesR still gives null, somes told me that when catching the controle with rptArticleContent.FindControl i should add something so it would be applied on every item bounded, what is that missing clue.?? what should be added?
You don't want to use rptArticleContent in the function, rather e.Item which will return the current repeater item instance.
Related
I've got a button inside a repeater control, and I need to send some identifying information from the button to the onClick event so I know which ID has been clicked. My asp.net code (in part) looks like this:
<asp:Repeater ID="ParentRepeater" runat="server" OnItemDataBound="ParentRepeater_ItemDataBound">
<ItemTemplate>
<div class="bevelBox"><h3><b><%#Eval("AlbumName") %> Photo Gallery</b></h3></div>
<asp:Repeater ID="PhotoRepeater" runat="server" onitemcommand="PhotoRepeater_ItemCommand" OnItemDataBound="PhotoRepeater_DataBinding">
<HeaderTemplate>
<div class="bevelBox">
<Table>
<tr>
<td style="width:160px"><h3>Concert Photo</h3></td>
<td style="width:535px"></td>
<td><asp:Button ID="btnAddPhoto" runat="server" OnClick="btnAddPhoto_Click" Text="Add Yours" CommandArgument='<%#Eval("AlbumID") %>' UseSubmitBehavior="false" /></td>
</tr>
</Table>
</div>
Someone told me I could use the CommandArgument command to get this data to the code-behind.
On the C# side, I have this:
protected void btnAddPhoto_Click(object sender, EventArgs e)
{
Button btn = (Button)sender;
string ggg = btn.CommandArgument.ToString();
mdlAddPhoto.Enabled = true;
mdlAddPhoto.Show();
}
I put a break point on the "string gggg" line, just to see what is being passed back. There's nothing indicating the <%#Eval("AlbumID") %> is being passed back.
Can anyone tell me how I can get this ID data passed back to the C# side?
I am trying to set the text of the label control which is inside detailsview but it's not working. But it's showing error "Object reference not set to an instance of an object."
can anyone guide me please.. ??
My front end code is:
<asp:Panel ID="sub_question_panel" runat="server">
<asp:DetailsView ID="DetailsView1" runat="server" CellPadding="6" ForeColor="#333333" AutoGenerateRows="false" GridLines="None" >
<Fields>
<asp:TemplateField>
<ItemTemplate>
<table id="Question_view_table">
<tr>
<td style="font-family:Arial Rounded MT;">
<label id="Question_no"><span style="font-size:20px;">Question</span>:</label>
<asp:Label ID="Ques_id_label" runat="server" Text="Label"></asp:Label></td>
</tr>
<tr>
<td style="height:20px"></td>
</tr>
<tr>
<td style="font-family:'Times New Roman'; font-size:18px; ">
<label id="Question_detail"><%# Eval ("Question") %></label>
</td>
</tr>
<tr>
<td style="font-family:'Times New Roman'; font-size:18px;">
<ol style="list-style:upper-alpha">
<li>
<label id="optn1">   <%# Eval ("Option1") %></label></li>
<li>
<label id="optn2">   <%# Eval ("Option2") %></label></li>
<li>
<label id="optn3">   <%# Eval ("Option3") %></label></li>
<li>
<label id="optn4">   <%# Eval ("Option4") %></label></li>
</ol>
</td>
</tr>
</table>
</ItemTemplate>
</asp:TemplateField>
</Fields>
</asp:DetailsView>
</asp:Panel>
My back end code is:
protected void Page_Load(object sender, EventArgs e)
{
int question_id = 1;
Label Question_Id = DetailsView1.FindControl("Ques_id_label") as Label;
Question_Id .Text = Convert.ToString(question_id);
}
You must use the FindControl for a row, not DataListView
You want to find your label by id, But which one? For each row you have a label with id 'Ques_id_label' . So to find a specific label you must specify the intended row. I did not work with DataLisView but I know that it is logically similar to Asp:Repeater . To find a control in a row of a Repeater when a command is sent from a row:
protected void SaveAnswer(Object Sender, RepeaterCommandEventArgs e)
{
Label Ques_id_label = (Label)e.Item.FindControl("Ques_id_label");
Which with e.item you specify the intended row.
You use FindControl to find Ques_id_label, but then reference it normally anyway: Ques_id_label.Text =
It should be Question_Id.Text = Convert.ToString(question_id);, with the ID you assigned with FindControl.
But did it even compile? Do you use an editor like Visual Studio? Because when I tried your snippet it gave the error The name 'Ques_id_label' does not exist in the current context, as it is supposed to.
I have a listview control which is populated with data from a database. I have used the label to display that data. Now I need to use the value of that label in some other place. I am trying to access the text value of the label control but it says
Object reference not set to an instance of an object.
But I do have value in the label.
<asp:ListView ID="msg_list" runat="server">
<ItemTemplate>
<table>
<tr class="myitem">
<td>
<asp:Label ID="reg_id_reply" runat="server" Text="helo" Visible="false" />
<asp:Label role="menuitem" ID="msg_lbl" runat="server" text='<%#Eval("msg")%>' /><i style=" color:Gray; " > from
<asp:Label ID="tme" runat="server" Text='<%#Eval("name")%>' />
<i> on </i>
<asp:Label ID="tmelbl" runat="server" Text='<%#Eval("tme")%>'/>
<a id="msg-reply" class="btn button" data-toggle="modal" data-target="#msg-rply" style="cursor:pointer;" ><i class="glyphicon glyphicon-share-alt white"> </i></a> </td>
<hr style=" margin-top:1px; margin-bottom:1px; " />
</tr>
</table>
<%--<hr style=" margin-top:1px; margin-bottom:1px; " />--%>
</ItemTemplate>
</asp:ListView>
This is how i tried to access the text of the label.Note that the code below is inside a button click event onClick of buttom.
Label mylbl = (Label)msg_list.FindControl("reg_id_reply");
string rid = mylbl.Text;
According to the description for Control.FindControl Method (String):
This method will find a control only if the control is directly contained by the specified container.
The direct container that your label is contained within is the ItemTemplate. Therefore you may need to build a recursive search for your label if you are starting with the listview. You could try the following code that is suggested from this MSDN page:
private Control FindControlRecursive(Control rootControl, string controlID)
{
if (rootControl.ID == controlID) return rootControl;
foreach (Control controlToSearch in rootControl.Controls)
{
Control controlToReturn = FindControlRecursive(controlToSearch, controlID);
if (controlToReturn != null) return controlToReturn;
}
return null;
}
However also note that the listview may change the id values of components in the item template. If you know the item index you want then you can use the method suggested in this post:
var theLabel = this.ChatListView.Items[<item_index>].FindControl("reg_id_reply") as Label;
Edit: Found the solution, and posted the answer below.
In my ASP.NET c# project, I have a ListView (ParentList) bound to a DataSource. Within the ParentList, inside the ItemTemplate, I have another Repeater (ChildList) bound to an attribute of each ListViewDataItem.
<asp:ListView ID="ParentList" runat="server" DataSourceID="objectDataSourceID" DataKeyNames="ID">
<ItemTemplate>
<tr>
<td>
<asp:Label ID="Label1" runat="server" Text='<%# Eval("Attribute1") %>' />
</td>
<td valign="top">
<asp:Repeater ID="ChildList" runat="server" DataSource='<%# Eval("Attribute2ReturnsAnotherList") %>'>
<HeaderTemplate>
<ul>
</HeaderTemplate>
<ItemTemplate>
<li>
<%# DataBinder.Eval(Container.DataItem, "childAttribute") %>
</li>
</ItemTemplate>
<FooterTemplate>
</ul>
</FooterTemplate>
</asp:Repeater>
</td>
</tr>
</ItemTemplate>
<LayoutTemplate>
...
</LayoutTemplate>
</asp:ListView>
The code above works just fine, everything renders great. Now I want to add a link that will show/hide the ChildList. Something like the below:
<td valign="top">
<a href="javascript:ToggleListVisibility()" >Show/Hide</a>
<asp:Repeater ID="ChildList" runat="server" DataSource='<%# Eval("Attribute2ReturnsAnotherList") %>'>
</asp:Repeater>
</td>
How can I achieve this? I can't just use getElementById as I normally would, as the ul lists are within a Repeater nested inside the ListView. I tried obtaining the parentNode, then accessing the children and toggling the visibility of the ul element within:
function ToggleListVisibility(source) {
var childrenlist = source.parentNode.children;
for (var i = 0; i < childrenlist.length; i++) {
if (childrenlist[i].tagName == 'ul') {
if (childrenlist.style.display == "none") {
childrenlist.style.display = "block";
} else {
childrenlist.style.display = "none";
}
}
}
}
<a href="javascript:ToggleListVisibility(this)" >Show/Hide</a>
but that didn't work. IE's 'error on page' gave me this error:
The parentNode is null or not an object.
I also tried setting the a runat="server" attribute to my ul element, then using <%# ulID.ClientID %> to pass the ul id to the Js function, but visual studio complained:
Server elements cannot span templates.
Finally, I tried just passing the ul object into the Js function, like this:
function ToggleListVisibility(src) {
if (src.style.display == "none") {
src.style.display = "block";
} else {
src.style.display = "none";
}
}
<a href="javascript:ToggleListVisibility(ulID)" >Show/Hide</a>
...
<ul id="ulID">
which works, but it toggles the visibility for the ChildList in all rows within my ParentList. I want it to only toggle the visibility for the ChildList in its own row.
I'm at a loss of what to do. JavaScript is not my forte, and I would appreciate if someone can provide some pointers. Thanks in advance.
Ok hopefully this will get you going - it worked for me in hiding a list. My source HTML looks like this:
<table>
<tbody>
...
<tr>
<td>
Hide
<ul>
<li>One</li>
<li>Two</li>
<li>Three</li>
</ul>
</td>
</tr>
...
</tbody>
</table>
<script type="text/javascript">
function toggleListVisibility(src) {
var childrenList = src.nextSibling.nextSibling;
childrenList.style.display = "none";
}
</script>
Note I had to use two "nextSibling"'s due to a text node that is created right after the "hide" anchor. Depending on how you structure your HTML, that bit will be different.
I found the painfully simple answer that makes me feel like a doofus. All I needed to do is wrap my Repeater in a <div> element, then show/hide the entire thing.
<a href="javascript:ToggleListVisibility('<%# Container.FindControl("divWrapper").ClientID %>')" >Show/Hide</a>
<div id="divWrapper" runat="server">
<asp:Repeater ID="ChildList" runat="server">
</asp:Repeater>
</div>
function ToggleListVisibility(id) {
var wrapper = document.getElementById(id);
if (wrapper.style.display == "none") {
wrapper.style.display = "block";
} else {
wrapper.style.display = "none";
}
}
Hooray for overthinking!
Given the following HTML:
<asp:content id="Content1" contentplaceholderid="mainContent" runat="server">
<div class="scrollRow">
<table width="100%">
<tr>
<td width="25%">Site name: <b>My site</b></td>
<td>Created on 12th Aug 2010</td>
<td align="right"><button onclick="doRevert(1)">Revert to this</button></td>
</tr>
</table>
</div>
<div class="scrollRow">
<table width="100%">
<tr>
<td width="25%">Site name: <b>Another site</b></td>
<td>Created on 3rd Aug 2010</td>
<td align="right"><button onclick="doRevert(1)">Revert to this</button></td>
</tr>
</table>
</div>
<div class="scrollRow scrollRowOn">
<table width="100%">
<tr>
<td width="25%">Site name: <b>Another site</b></td>
<td>Created on 3rd Aug 2010</td>
<td align="right"></td>
</tr>
</table>
</div>
</asp:content>
Which is a list of rows, how am I programatically meant to generate these after I have retrieved the SQL rows from the code behind? Do I need to make my own control, or something along those lines?
Try something along these lines:
<asp:Repeater ID="Repeater1" runat="server" OnItemDataBound="Repeater1_OnItemDataBound">
<ItemTemplate>
<div class='<%# SetClass(Eval("SiteId")) %>'>
<table width="100%">
<tr>
<td width="25%">Site name: <b><%# Eval("SiteName") %></b></td>
<td>Created on <%# DataBinder.Eval(Container.DataItem, "CreateDate", "{0:dd MMM yyyy}")%></td>
<td align="right"><button id="btnRevert" runat="server" onclick="doRevert(1)">Revert to this</button></td>
</tr>
</table>
</div>
</ItemTemplate>
</asp:Repeater>
In the codebehind Repeater1_OnItemDataBound event you could set the button to be visible or not, depending on whether the item is the current one.
protected void Repeater1_OnItemDataBound(object sender, RepeaterItemEventArgs e)
{
RepeaterItem item = e.Item;
if (item.ItemType == ListItemType.AlternatingItem || item.ItemType == ListItemType.Item)
{
Site site = e.Item.DataItem as Site; //List<Site> is what you are binding to the repeater
if (site.SiteId == currentSiteId)
{
var btn = e.Item.FindControl("btnRevert") as Button;
if (btn != null)
{
btn.Visible = false;
}
}
}
}
CSS Classes for your items can be set like this:
protected string SetClass(object obj) {
int siteId;
if (int.TryParse(obj.ToString(), out siteId)){
if (siteId == currentSiteId) //currentSiteId determined elsewhere
{
return "scrollRow";
}
}
return "scrollRow scrollRowOn";
}
There are a lot of ways to get to this, of course, but here's one (possibly not the best, but that's subjective anyway):
Assuming C# web forms and ADO.Net, and assuming you need precisely that html, you could loop over the rows in the DataSet and output the html.
DataSet ds = {data set from your sql}
StringBuilder html = new StringBuilder();
foreach (DataRow row in DataSet.Tables[0].Rows) {
html.Append( string.Format(#"<div class=""scrollRow"">
<table width=""100%"">
<tr>
<td width=""25%"">Site name: <b>{0}</b></td>
<td>Created on {1}</td>
<td align="right"><button onclick="doRevert(1)">Revert to this</button></td>
</tr>
</table>",row["sitename"], row["createdate"]));
}
You could include the html by having an <asp:Literal> in the page code and setting the Text property.
You could also do it by creating System.Web.UI.WebControls.Table nodes in the code behind and adding TableRows and TableCells to them, using the same loop, and then adding those to the page using. Given what you've given us thus far, you seem to be adding controls to a page with a MasterPage, so you would need to add your tables to the Master's ContentPlaceHolder, which you can find and add controls to like so:
ContentPlaceHolder ph = (ContentPlaceHolder)this.Master.FindControl( "ContentPlaceHolder1" );
foreach (DataRow row in DataSet.Tables[0].Rows) {
Panel pnl = new Panel();
Table tbl = new Table();
TableRow tblrow = new TableRow();
TableCell cell1 = new TableCell();
cell1.Text = string.Format("Site name: <b>{0}</b>",row["sitename"]);
row.Cells.Add(cell1);
tbl.Rows.Add(tblrow);
pnl.Controls.Add(tbl);
ph.Controls.Add(pnl);
}
You can set properties on the TableRows and TableCells, but if you do it this way you will lose some control over the html that's generated, most notably the html ID attributes. You don't seem to be using those, so perhaps that's ok.
I would suggest the repeater control. You can use it something like this:
<asp:Repeater runat="server" id="myRepeater">
<ItemTemplate>
<div class="scrollRow scrollRowOn">
<table width="100%">
<tr>
<td width="25%">Site name: <b><% Eval("SiteName")%></b></td>
<td>Created on <% Eval("CreatedOn")%></td>
<td align="right"></td>
</tr>
</table>
</div>
</ItemTemplate>
</asp:Repeater>
Then you need to bind your data to it in the Page_Load event:
myRepeater.DataSource = myData;
myRepeater.DataBind();
Where my data is the data that you retrieve from the database.