asp.NET: How to access repeater generated elements? - asp.net

i have a repeater than creates a table:
<itemtemplate>
<tr id="theTableRow" runat="server">
<td>
<asp:LinkButton runat="server"
OnClientClick="todo"
Text="Do Something" />
</td>
</tr>
</itemtemplate>
Note: the OnClientClick="todo" line.
In the final rendered code, i want the todo to contain a call to a javascript function, passing:
the ID of the generated table row, and
the Eval of a property of the currently bound object
And now for some pseudo-code:
Pseudocode 1:
OnClientClick="DoSomething(theTableRow, CromulentGuid); return false;"
Pseudocode 2
OnClientClick="javascript:DoSomething(theTableRow, CromulentGuid); return false;"
Pseudocode 3
OnClientClick="javascript:DoSomething(theTableRow, <%# Eval("CromulentGuid") %>); return false;"
Pseudocode 4
OnClientClick="javascript:DoSomething(<%= theTableRow %>, <%# Eval("CromulentGuid") %>); return false;"
Pseudocode 5
OnClientClick='javascript:DoSomething(<%= Eval(theTableRow) %>, <%# Eval("CromulentGuid") %>); return false;'
Whatever the ASP.NET code used, i want the rendered HTML to be:
<tr id="ctl00__itemRepeater_ctl01_theTableRow">
<td>
<a
onclick="DoSomething('ctl00__itemRepeater_ctl01_theTableRow', '19a149db-5675-4eee-835d-3d78372ca6f9'); return false;"
href="javascript:__doPostBack('ctl00$itemRepeater$ctl01$ctl04','')">
Do Something
</a>
</td>
</tr>
i would also be okay with:
<tr id="ctl00__itemRepeater_ctl01_theTableRow">
<td>
<a
onclick='DoSomething("ctl00__itemRepeater_ctl01_theTableRow", "19a149db-5675-4eee-835d-3d78372ca6f9"); return false;'
href="javascript:__doPostBack('ctl00$itemRepeater$ctl01$ctl04','')">
Do Something
</a>
</td>
</tr>
Note: i'm okay with the 2nd form since i know it is functionally identical, and ASP.NET code cannot generate the former, even if the latter is less readable.
Related questions:
ASP.NET: How to access repeater generated elements from javascript?

The better solution is to put the presentation logic in the business layer:
Presentation:
<asp:LinkButton runat="server"
OnClientClick="<%# GetItemClientClick((MySomething)Container.DataItem) %>"
Text="Do stuff" />
Business Logic
protected string GetItemClientClick(MySomething item)
{
...
String szOnClientClick =
"return DeleteItem(this, "+
Toolkit.QuotedStr(item.NodeGUID.ToString()) + ", "+
Toolkit.QuotedStr(GetItemText(item))+");";
return szOnClientClick;
}
Much cleaner. Much more readable. Much more maintainable.

You can use the OnItemDataBound event to alter each element in your code. Since you're particular about the HTML I might also recommend using hybrid controls rather than asp controls. For example:
<itemtemplate>
<tr id="theTableRow" runat="server">
<td>
<a runat="server"
onclick="todo(this.parent.parent, '<%# Eval("Property") %>');return false;" >
Do Something
</a>
</td>
</tr>
</itemtemplate>
This probably isn't 100% perfect, as I just typed it directly in the reply window and I always screw up the Eval() syntax on my first go, but it should help some.

Why not put the JS on the table row?
<tr onClick="DoSomething(this, '<%# Eval("GUIDColumn") %>')"; ><td>
<%# Eval("ColumnText") %>
</td></tr>
This gets you a reference to the table row, and the data that you're needing. It does break downlevel support, so browsers under IE6 won't really work as expected, but that's pretty much par for the course these days.
Two other possibilities are to utilize the Datagrid/Gridview object and the OnItemDatabound aspects or to build the table in code utilizing the ASP.NET TABLE control, and iterating through your datasource manually.

Related

ASP.NET - IF Statement in Listview doesnt work on aspx page, is there an alternative?

I have bound a DataSet to a ListView. In the ListView ItemTemplate, if a row value is empty, I do not want it, or the <td> element it is enclosed in to display.
In my code, the first row value will display. However, when I try to use the If statement on the second <td> element, that will not display.
<asp:ListView ID="ListView1" runat="server" GroupPlaceholderID="groupPlaceHolder1" ItemPlaceholderID="itemPlaceHolder1">
<LayoutTemplate>
<table>
<asp:PlaceHolder runat="server" ID="groupPlaceHolder1"> </asp:PlaceHolder>
</table>
</LayoutTemplate>
<GroupTemplate>
<tr>
<asp:PlaceHolder runat="server" ID="itemPlaceHolder1"> </asp:PlaceHolder>
</tr>
</GroupTemplate>
<ItemTemplate>
<td>
<%# Eval("textItem1") %>
</td>
<% if (!String.IsNullOrEmpty(textItem2){ %>
<td>
<%# Eval("textItem2") %>
</td>
<%} %>
</ItemTemplate>
</asp:ListView>
That If statement works in an aspx page if its NOT being used in a ListView, Repeater, or GridView (or does it?). I need to be able to check if that string row value is empty and not display it or the <td> element it is enclosed in. I am not against a solution that uses code-behind. Is there another way to do this then my attempt?
I used a pretty simple method solution..
In the above code, I swapped out this...
<% if (!String.IsNullOrEmpty(textItem2){ %>
<td>
<%# Eval("textItem2") %>
</td>
<%} %>
For this...
<%# writeText(Eval("textItem2").ToString())%>
And placed this method in the code behind...
public string writeText(string kiss)
{
if (!String.IsNullOrEmpty(kiss))
return "<td> " + kiss + "</td>";
else
return null;
}

Set TD at runtime (depending on Label.text)

I have some tabular data, when the label has some specific value I need to make it show off.
Trying to do by styling the TD.
My C# sets the value for Label1.text
Can you think of any other way for doing so? It's throwing ambiguity error.
<% if (Label1.Text == "1") { %>
<td style="background:#ffedad; border:#e3a345; color:#cd5c0a"><asp:Label ID="Label1" runat="server" /></td>
<% } else {%>
<td><asp:Label ID="Label1" runat="server" /></td>
<% } %>
EDIT
Did something else (and cleaner).
Worked on some code behind variables along with some new td.alt on my css file to get the value of the label. If it's 1, then I set a
classLabel variable to alt and then I just set the class inside the td
<td class="<%classLabel%>"><asp:Label ID="Label1" runat="server" /></td>
Still, I'm getting and error on this last line in my aspx page, any ideas where the error is?
You can try this with a single line :
<td <%=Label1.Text != "1"?"":"style='background:#ffedad; border:#e3a345; color:#cd5c0a'"%>><asp:Label ID="Label1" runat="server" /></td>
Setting the style code behind and with a css class would be cleaner IMHO
Hope this will help
You can call the code behind method which will return the formatted HTML string that can be directly rendered by the browser. In that code behind method you can do almost anything: access any type of database or any business logic.
Possible return div element encapsulating the content (without style).
You can return divs with different ids or classes by having if-else logic inside the code-behind method. Then you can write different CSS styles to apply to different divs.
<% if (Label1.Text == "1") { %>
<td style="background:#ffedad; border:#e3a345; color:#cd5c0a">
<%# generateOutput() %></td>
<% } else {%>
<td> <%# generateOutput() %> </td>
<% } %>
Instead of having if-else in asp.net markup, you can simply have
<%# generateOutput() %>
and return the whole content from code behind and write styles in CSS files.
If the content to be displayed is less or less complicated this second approach will work, otherwise you may prefer first approach.
However if you are accessing the data directly from database you can you ASP.NET data controls like GridView, style them in templates and also filter the data using querystring or form values.

Foreign key table field not displaying within a standalone dynamic data enabled list view

I've gone through hundreds of Google result pages, trying to find an answer for this over the past couple of days.
Using a standalone dynamic data page to display a table, using an EntityDataSource, with one of the fields being a foreign key to a sub-table. I want it to display the value from the sub-table. I've been playing with a simplified case using the NorthWinds database (see code below). If I assign the DynamicControl a DataField="Supplier", it displays the sub-table/class name ("DAL.Supplier") instead. If I try assigning DataField="Supplier.CompanyName", it errors with "The table 'Product' does not have a column named 'Supplier.CompanyName'". Since I want to take advantage of dynamic data's editing features, using a templated field with <%# Eval("Supplier.CompanyName") %> is out.
Is this just not possible with a stand-alone dynamic data page? It clearly works fine within a fully scaffolded system. Or am I (hopefully) just missing something? Thank you.
Test.aspx
<%# Page Title="" Language="VB" MasterPageFile="~/Master/Site.master" AutoEventWireup="false" CodeFile="Test.aspx.vb" Inherits="Test" %>
<asp:Content ID="Content3" ContentPlaceHolderID="BodyContent" Runat="Server">
<asp:ListView ID="ListView1" runat="server" DataSourceID="theDataSource" DataKeyNames="ProductID">
<ItemTemplate>
<tr>
<td>
<asp:DynamicControl runat="server" DataField="ProductID" Mode="Edit" />
</td>
<td>
<asp:DynamicControl runat="server" DataField="ProductName" Mode="Edit" />
</td>
<td>
<asp:DynamicControl runat="server" DataField="Supplier" Mode="Edit" />
</td>
<td>
<asp:DynamicControl runat="server" DataField="UnitPrice" Mode="Edit" />
</td>
<td>
<asp:DynamicControl runat="server" DataField="Discontinued" Mode="Edit" />
</td>
</tr>
</ItemTemplate>
<LayoutTemplate>
<table runat="server">
<tr runat="server">
<td runat="server">
<table id="itemPlaceholderContainer" runat="server" border="0">
<tr runat="server">
<th runat="server">
ProductID
</th>
<th runat="server">
ProductName
</th>
<th runat="server">
Supplier
</th>
<th runat="server">
UnitPrice
</th>
<th runat="server">
Discontinued
</th>
</tr>
<tr id="itemPlaceholder" runat="server">
</tr>
</table>
</td>
</tr>
<tr runat="server">
<td runat="server">
</td>
</tr>
</table>
</LayoutTemplate>
</asp:ListView>
<asp:EntityDataSource ID="theDataSource" runat="server"
ConnectionString="name=NorthwindEntities"
DefaultContainerName="NorthwindEntities" EnableDelete="True"
EnableFlattening="False" EnableInsert="True" EnableUpdate="True"
Include="Supplier"
EntitySetName="Products">
</asp:EntityDataSource>
</asp:Content>
Test.aspx.vb
Imports System.Web.DynamicData
Imports DAL
Partial Class Test
Inherits System.Web.UI.Page
Protected table As MetaTable
Protected Sub Page_Init(sender As Object, e As System.EventArgs) Handles Me.Init
Listview1.EnableDynamicData(GetType(Product))
table = theDataSource.GetTable()
Title = table.DisplayName
End Sub
End Class
Problem solved. When all of this had started, I had originally gotten the error message:
Could not determine a MetaTable. A MetaTable could not be determined for the data source 'EntityDataSource1' and one could not be inferred from the request URL. Make sure that the table is mapped to the dats source, or that the data source is configured with a valid context type and table name, or that the request is part of a registered DynamicDataRoute
Trying to track that down led me to getting rid of the asp:DynamicDataManager markup, and replacing it in the code-behind with:
Listview1.EnableDynamicData(GetType(Product))
table = theDataSource.GetTable()
That turns out to have led me down the proverbial rabbit hole... While it got rid of the MetaTable error, it inadvertently caused the problem I wrote about above. Many thanks to: http://daviworld.net/?tag=/DynamicDataManager who points out that this error message is actually caused by:
This is due to an issue with the Designer code generation. When you select a DataSource for the GridView control, it does not add the ContextTypeName Attribute to the EntityDataSourceControl.
Once I removed the lines of code above, and added back in the asp:DynamicDataManager to the markup, and then added a ContextTypeName="DAL.NorthwindEntities" to the EntitiyDataSource, everything now works as one would wish it to.
Yeah true what u said. im at the same place where u got stuck. am running from pillar to post with fire in my belly but i guess it might extinguish soon.
how can it be so screwed up that u cannot work outside the scaffolding mechanism, all u are really doing is borrowing a dynamicdatamanager so u can stay templatised across both their framework and your newly added framework.
the way i got into this hole is when i try to display multiple entities data on the same page. thumb of rule seems to be single entity , single page. whatever im on da error for now. give it another few days before i open up the bottle again.. let there be beer !!!

Counting ItemTemplate in ListView from XmlDataSource in ASP.net

I have the following code. It works as is, but... I am not always going to have an even number of items in the RSS feed So, at the end of the table, I might have only one table cell on the last row. So, is there a way to count the number of ItemTemplates and AlternatingItemTemplate, so if it is an odd number I would be able to add another cell <td> </td></tr> and close the table row?
<asp:XmlDataSource ID="SomeFeed" DataFile="TestSomeRSS.xml" XPath="rss/channel/item" runat="server"></asp:XmlDataSource>
<asp:ListView ID="SomeFeedScroller" DataSourceID="SomeFeed" ItemPlaceholderID="SomePlcID" runat="server">
<LayoutTemplate>
<table id="ListingsTable" cellpadding="0" cellspacing="0" align="center">
<asp:PlaceHolder ID="SomePlcID" runat="server"></asp:PlaceHolder>
</table>
</LayoutTemplate>
<ItemTemplate>
<tr style="vertical-align:top;">
<td class="bnotes" style="width:325px;padding:5px;">
<%# XPath("title")%><br />
<%# XPath("description")%><br />
</td>
</ItemTemplate>
<AlternatingItemTemplate>
<td class="bnotes" style="width:325px;padding:5px;">
<%# XPath("title")%><br />
<%# XPath("description")%><br />
</td>
</tr>
</AlternatingItemTemplate>
</asp:ListView>
Thanks in advance for your help.
I'm not sure what you're asking, but why not just put a complete row in the ItemTemplate and AlternatingItemTemplate, like this:
<ItemTemplate>
<tr style="vertical-align:top;">
<td class="bnotes" style="width:325px;padding:5px;">
<%# XPath("title")%><br />
<%# XPath("description")%><br />
</td>
</tr>
</ItemTemplate>
<AlternatingItemTemplate>
<tr style="vertical-align:top;">
<td class="bnotes" style="width:325px;padding:5px;">
<%# XPath("title")%><br />
<%# XPath("description")%><br />
</td>
</tr>
</AlternatingItemTemplate>
That way you don't have to figure it out yourself - just let the control render itself.
EDITED TO ADD
Looking at your posted code again, it looks like you might have been attempting one row of alternating cell styles. I think you misunderstood the intent of the ItemTemplate and AlternatingItemTemplates; they usually deal with the fields (columns) of a given record.
In this case, you'd have the first RSS feed item in an ItemTemplate, then the second RSS feed item in an AlternateItemTemplate (i.e., another row), then the third RSS feed item in an ItemTemplate and so on.
I hope this helps - if I've misunderstood what you're trying to do let me know.
2nd Edit
Based on the example layout posted in the comments, I think the DataList Class would be a better option, as you can easily specify multiple columns (using the RepeatColumns property). Something like this:
<asp:XmlDataSource ID="SomeFeed" DataFile="TestSomeRSS.xml" XPath="rss/channel/item" runat="server">
</asp:XmlDataSource>
<asp:DataList ID="SomeFeedScroller" DataSourceID="SomeFeed"
RepeatColumns="2" RepeatDirection="Horizontal"
RepeatLayout="Table" runat="server">
<ItemStyle CssClass="bnotes" Vertical-Align="top" Width="325px" />
<AlternatingItemStyle CssClass="bnotes" vertical-Align="top" Width="325px" />
<ItemTemplate>
<%# XPath("title")%><br />
<%# XPath("description")%>
</ItemTemplate>
<AlternatingItemTemplate>
<%# XPath("title")%><br />
<%# XPath("description")%>
</AlternatingItemTemplate>
</asp:DataList>
The above is not tested, but the general idea was to keep the formatting as close to what was in the ListView as possible.
Another possible approach might be something similar to this thread on having multiple columns in a Repeater control: Multiple columns in a repeater.
The DataList control supports editing, selecting, updating, etc like ListView. The Repeater control does not.

Creating a textbox in ASP.Net with unique ID programatically

I'm wondering what the best way to create text boxes in my loop here so that the IDs are unique instead of just "TextBox" for all of them. I need to add up the Price based on the Price per unit and the Quantity.
My items are loaded from a database so there could be any number of them, so I need to generate the fields on the fly. I was thinking maybe an array of fields could be used like in a form application, or is this not the right way to go?
I tried googling an answer, but maybe I'm just not wording my question well. It seems like this should be solved rather easily, but I just can't find the answer.
Here is my code:
<table class="proposal" width="800">
<tr>
<th>Item</th>
<th>Price per Unit</th>
<th>Quantity</th>
<th>Price</th>
</tr>
<% int x = 0; %>
<% do
{
%>
<tr>
<td valign="top">
<%= this.name[x] %><br />
<%= this.desc[x] %></td>
<td valign="top" align="right"><%= "$" + this.price[x] %></td>
<td valign="top" align="center"><asp:TextBox ID="TextBox" runat="server" Width="75px"></asp:TextBox></td>
<td valign="top" align="right"></td>
</tr>
<% x++;
} while (x != this.y);
%>
</table>
You can't do a dynamic id for an asp.net TextBox. Could you use plain html <input type="text"> text boxes instead? Then you could assign whatever id you want.
Another approach would be to use a repeater control to generate your table. Each TextBox will then automatically get a unique id. If you need to get the ids in code, then in the repeater's ItemDataBound method, use FindControl to get a handle to the TextBox and read the ids/
You'll want to use the Repeater control as in this demonstration.

Resources