ASP.Net: Conditional Logic in a ListView's ItemTemplate - c#

I want to show certain parts of an ItemTemplate based according to whether a bound field is null. Take for example the following code:
(Code such as LayoutTemplate have been removed for brevity)
<asp:ListView ID="MusicList" runat="server">
<ItemTemplate>
<tr>
<%
if (Eval("DownloadLink") != null)
{
%>
<td>
Link
</td>
<%
} %>
</tr>
</ItemTemplate>
</asp:ListView>
The above gives the following run-time error:
Databinding methods such as Eval(),
XPath(), and Bind() can only be used
in the context of a databound control.
So how can put some conditional logic (like the above) in an ItemTemplate ?

What about binding the "Visible" property of a control to your condition? Something like:
<asp:ListView ID="MusicList" runat="server">
<ItemTemplate>
<tr runat="server" Visible='<%# Eval("DownloadLink") != null %>'>
<td>
<a href='<%#Eval("DownloadLink") %>'>Link</a>
</td>
</tr>
</ItemTemplate>
</asp:ListView>

To resolve "The server tag is not well formed." for the answers involving visibility, remove quotes from the Visible= parameter.
So it will become:
<tr runat="server" Visible=<%# Eval("DownloadLink") != null ? true : false %>>

I'm not recommending this as a good approach but you can work around this issue by capturing the current item in the OnItemDataBound event, storing it in a public property or field and then using that in your conditional logic.
For example:
<asp:ListView ID="MusicList" OnItemDataBound="Item_DataBound" runat="server">
<ItemTemplate>
<tr>
<%
if (CurrentItem.DownloadLink != null)
{
%>
<td>
Link
</td>
<%
} %>
</tr>
</ItemTemplate>
</asp:ListView>
And on the server side add the following code to your code behind file:
public MusicItem CurrentItem { get; private set;}
protected void Item_DataBound(object sender, RepeaterItemEventArgs e)
{
CurrentItem = (MusicItem) e.Item.DataItem;
}
Note that this trick will not work in an UpdatePanel control.

If you have 2 different structure that are to be rendered according to a condition then use panels
<asp:ListView ID="MusicList" runat="server">
<ItemTemplate>
<tr>
<asp:Panel ID="DownloadNull" runat="server" Visible="<%# Eval("DownloadLink") == null %>" >
<td> Album Description BlaBlaBla <img src="../images/test.gif"> </td>
</asp:Panel>
<asp:Panel ID="DownloadNotNull" runat="server" Visible="<%# Eval("DownloadLink") != null %>" >
<td> Album Description BlaBlaBla <img src="../images/test.gif">
<a href='<%# Eval("DownloadLink")' >Download</a>
.....
</td>
</asp:Panel>
</tr>
</ItemTemplate>
</asp:ListView>

Related

Assign Control ID using Server Tag in ASP.NET

I have a aspx page and want to generate the page dynamically using a DataTable using server tags.
My code looks like this:
<table style="width: 100%">
<% foreach (System.Data.DataRow row in UserReports.Rows) { %>
<tr>
<td>
<% if (row["ID"] != DBNull.Value) { %>
<div>
<table>
<tr>
<td>
<p><%=row["ReportTitle"]%></p>
</td>
<td>
<asp:Button ID="btnRunReport_<%=row["ID"]%>" runat="server" Text="Open" />
</td>
</tr>
</table>
</div>
<% } %>
</td>
</tr>
<% } %>
</table>
When I navigate to my page I get error:
Server tags cannot contain <% ... %> constructs
The error happens here and I tried different comination of using the server tag but could not find out the right way of assigning the ID to the dynamically creating button.
<asp:Button ID="btnRunReport_<%=row["ID"] %>"
If you want to use a DataBinding expression, you need to write is like this
//this does not work
<asp:Button ID='<%# "btnRunReport_" + row["ID"] %>' runat="server" Text="Open" />
//this does because you cannot dynamically set the ID but every other property
<asp:Button ID="Button1" CssClass='<%# "btnRunReport_" + row["ID"] %>' runat="server" Text="Open" />
But you have to call DataBind() manually in Page_Load for that to work.
But I would recommend you look into a GridView Control. It creates a <table> in html and you can have other Controls in the ItemTemplates

Repeater shows wrong column content

I have a repeater to show an order confirmation. It is bound to a table generated with Entity Framework code first. The table contains the right information and the repeater shows all the information right except for the part where I show the totals which I paste below.
I believe that this part also works okay but quantity does not. For example if I add 5 products it will only show one, but if I put a break point and I run the code in debug mode I see that the value inserted in the Quantity table is 5 not 1, so the Quantity value on the table is inserted correctly, but the repeater reports 1.
Here is the code:
<asp:Repeater ID="rptConfirmOrder" runat="server">
<ItemTemplate>
<fieldset class = "OrderConfirmationFieldset"><legend class ="OrderDataLegend">Order Summary</legend>
<td align="left" width="60%" runat="server" id="Td25">
<asp:Label ID="lblQuantity" runat="server" Text="Quantity: " CssClass = "lblOrderConfirmation">
</asp:Label> <%# Eval("Quantity") %>
<br />
</td>
<td align="left" width="60%" runat="server" id="Td26">
<asp:Label ID="lblProductName" runat="server" Text="Product Name: " CssClass = "lblOrderConfirmation">
</asp:Label><%# Eval("ProductName" ,"{0:c}" ) %>
<br />
</td>
<td align="left" width="60%" runat="server" id="Td27">
<asp:Label ID="lblProductPrice" runat="server" Text="Product price: " CssClass = "lblOrderConfirmation">
</asp:Label> <%# Eval("ProductPrice" ,"{0:c}" ) %>
<br />
</td>
<td align="left" width="60%" runat="server" id="Td28">
<asp:Label ID="lblSubtotal" runat="server" Text="Subtotal: " CssClass = "lblOrderConfirmation">
</asp:Label> <%# Eval("Subtotal" ,"{0:c}" ) %>
<br />
</td>
<td align="left" width="60%" runat="server" id="Td29">
<asp:Label ID="lblTotal" runat="server" Text="Total: " CssClass = "lblOrderConfirmation">
</asp:Label> <%# Eval("Total" ,"{0:c}" ) %>
<br />
</td>
</ItemTemplate>
</asp:Repeater>
Can Anyone help?
Thank you in advance!
Your repeater markup doesn't look right.
have it as follows:
<asp:Repeater ID="rptConfirmOrder" runat="server" OnItemDataBound="rptConfirmOrder_ItemDataBound">
<ItemTemplate>
// stuff
</ItemTemplate>
</asp:Repeater>
And if you have it that way, and this was a paste error, then forget the value in the database/entity etc.
You can verify accurately, what value is being bound by tapping into the row data bound event as follows..
protected void rptConfirmOrder_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
var dataItem = e.Item.DataItem as YOUR_ENTITY_TYPE;
Debug.Assert(5 == dataItem.Quantity);
}
}
I think you may need to add the < itemtemplate > tags in after the opening repeater and close it off before the closing repeater tag.

If statement in repeaters ItemTemplate

I'm using an ASP.NET Repeater to display the contents of a <table>. It looks something like this:
<table cellpadding="0" cellspacing="0">
<asp:Repeater ID="checkboxList" runat="server" OnItemDataBound="OnCheckboxListItemBound">
<ItemTemplate>
<tr id="itemRow" runat="server">
<td>
Some data
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
</table>
It works fine, but i'd like to have an if() statement inside the ItemTemplate so i can conditionally determine if i want to print out a <tr> tag.
So i'd like to have something like this:
<table cellpadding="0" cellspacing="0">
<asp:Repeater ID="checkboxList" runat="server" OnItemDataBound="OnCheckboxListItemBound">
<ItemTemplate>
<% if ( (CurrentItemCount % 2) == 0 ) { %?>
<tr id="itemRow" runat="server">
<% } %>
<td>
Some data
</td>
<% if ( (CurrentItemCount % 2) == 0 ) { %?>
</tr>
<% } %>
</ItemTemplate>
</asp:Repeater>
</table>
Is there some way i can achieve this?
PS. The CurrentItemCount is just made up. I also need a way to get the current item count inside that if() statement. But i only seem to be able to get it from <%# Container.ItemIndex; %>, which can't be used with an if() statement?
Another way of doing this (if performance is not a problem):
<ItemTemplate>
<!-- "If" -->
<asp:PlaceHolder runat="server" Visible="<%# MyCondition %>">
<tr><td></td></tr>
</asp:PlaceHolder>
<!-- "Else" -->
<asp:PlaceHolder runat="server" Visible="<%# !MyCondition %>">
<tr><td></td></tr>
</asp:PlaceHolder>
</ItemTemplate>
If you're trying yo make a 2 columns table this could do the trick
<%# Container.ItemIndex % 2 == 0 ? "<tr class='itemRow'>" : "" %>
<td>
Some data
</td>
<%# Container.ItemIndex % 2 != 0 ? "</tr> : "" %>
Changed a couple of things: id="itemRow" for all rows would cause repeated ids what is not allowed.
Removed runat="server" since doesn't make sense on this context.
I have 2 examples, for the examples i will bind the repeater to a array of strings (demonstration purposes only)
void BindCheckboxList()
{
checkboxList.DataSource = new string[] { "RowA", "RowB", "RowC", "RowD", "RowE", "RowF", "RowG" };
checkboxList.DataBind();
}
Example 1: Create a methode in de codebehind casting the bound elements back en evaluate what ever value you'd like.
Create Methode in CodeBehind (example 1):
protected string StringDataEndsWith(object dataElement, string endsWith, string returnValue)
{
// for now an object of the type string, can be anything.
string elem = dataElement as string;
if (elem.EndsWith(endsWith))
{
return returnValue;
}
else
{
return "";
}
}
In the .aspx file (example 1):
<asp:Repeater ID="checkboxList" runat="server">
<HeaderTemplate>
<table style="padding:0px;margin:0px;">
</HeaderTemplate>
<ItemTemplate>
<%# StringDataEndsWith(Container.DataItem,"A","<tr id=\"itemRow\" runat=\"server\">") %>
<td>
<%# Container.DataItem %>
</td>
<%# StringDataEndsWith(Container.DataItem,"G","</tr>") %>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
Example 2: You could use a direct cast in the .aspx file
DirectCast example (no code behind):
<asp:Repeater ID="checkboxList" runat="server">
<HeaderTemplate>
<table style="padding:0px;margin:0px;">
</HeaderTemplate>
<ItemTemplate>
<%# Convert.ToString(Container.DataItem).EndsWith("A") ? "<tr id=\"itemRow\" runat=\"server\">" : "" %>
<td>
<%# Container.DataItem %>
</td>
<%# Convert.ToString(Container.DataItem).EndsWith("G") ? "</tr>" : "" %>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
I hope this is what you're looking for. Regards.
If you're wanting to do something on every other item, use the alternating item template.
http://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.repeater.alternatingitemtemplate.aspx
I would use codebehind:
protected void OnCheckboxListItemBound(Object sender, RepeaterItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.Item || e.Item.ItemType == ListItemType.AlternatingItem)
{
HtmlTableRow itemRow = (HtmlTableRow) e.Item.FindControl("itemRow");
itemRow.Visible = e.Item.ItemIndex % 2 == 0;
}
}

Design View ListView ASP.NET Logic

I am trying to input logic in the source view in Asp.Net ListView. The problem is that the program is writing on the screen false or true when executing "If (isItTrue(test))". Does anyone know how to solve this problem?
<%# test= Eval("testId")%>
<%
If (isItTrue(test)) Then
%>
<asp:Button ID="btnTest" runat="server" Text="Like" />
<%
Else
%>
<asp:Label runat="server" Text="hello" </asp:Label>
<%
End If
%>
You could use ItemDataBound to check informations like this and show or hide the controls using your condition. try something like this in your code behine:
protected void ListViewTest_ItemDataBound(object sender, ListViewItemEventArgs e)
{
// if it is data item
if (e.Item.ItemType == ListViewItemType.DataItem)
{
// call your function
if (isItTrue("test"))
{
// show the button
e.Item.FindControl("btnTest").Visible = true;
}
else
{
// show the label
e.Item.FindControl("lblTest").Visible = true;
}
}
}
And in your Listview, you could do something like this, setting the event and adding the controls on the place holder
<asp:ListView ID="ListViewTest" DataSourceID="..." OnItemDataBound="ListViewTest_ItemDataBound" runat="server">
<LayoutTemplate>
<table>
<tr>
<th>Column Name</th>
</tr>
<tr runat="server" id="itemPlaceholder" />
</table>
</LayoutTemplate>
<ItemTemplate>
<tr style="background-color: #CAEEFF" runat="server">
<td>
<%-- both controls are here --%>
<asp:Button ID="btnTest" runat="server" Visible="false" Text="Like"></asp:Button>
<asp:Label ID="lblTest" runat="server" Visible="false" Text="hello"></asp:Label>
</td>
</tr>
</ItemTemplate>
</asp:ListView>
Are you sure it's not this line: <%# test= Eval("testId")%> that is writing true or false to the output?

How to show a message inside a Repeater control if it has no data inside it?

I am developing an intranet web application. I am working now on the User Profile which shows four tables about the employee personal information, training courses, company short quizzes and his submitted ideas and suggestions.
What I want now is if the employee has no suggestions, the message such as ( You don't have any suggestions) inside the table instead of showing a table with its header without telling the user that he has no suggestions. So how to do that?
My ASP.NET code:
<asp:Repeater ID="Repeater4" runat="server" DataSourceID="SqlDataSource4">
<HeaderTemplate>
<div>
<table border="1">
<thead>
<tr>
<td colspan="3">
<center> <strong>Safety Suggestions</strong> </center>
</td>
</tr>
<tr>
<td>
<center> <strong>Suggestion Title</strong> </center>
</td>
<td>
<center> <strong>Description</strong> </center>
</td>
</tr>
</thead>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<p>
<%# Eval("Title") %>
</p>
</td>
<td>
<p>
<%# Eval("Description") %>
</p>
</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</div>
</FooterTemplate>
</asp:Repeater>
<asp:SqlDataSource ID="SqlDataSource4" runat="server"
ConnectionString="<%$ ConnectionStrings:testConnectionString %>" SelectCommand="SELECT dbo.SafetySuggestionsLog.Title, dbo.SafetySuggestionsLog.Description, dbo.SafetySuggestionsLog.Username
FROM dbo.SafetySuggestionsLog INNER JOIN
dbo.employee ON dbo.SafetySuggestionsLog.Username = dbo.employee.Username
WHERE (dbo.employee.Username = #Username)">
<SelectParameters>
<asp:Parameter Name="Username" />
</SelectParameters>
</asp:SqlDataSource>
You can use a footer template to manage massage, like this
step 1...
<FooterTemplate>
<%-- Label used for showing Error Message --%>
<asp:Label ID="lblErrorMsg" runat="server" Text="Sorry, no item is there to show." Visible="false">
</asp:Label>
</FooterTemplate>
step 2...
handle visibility of lable in Repeater_ItemDataBound event like
protected void Repeater_ItemDataBound(object sender, RepeaterItemEventArgs e)
{
Repeater rptDemo = sender as Repeater; // Get the Repeater control object.
// If the Repeater contains no data.
if (repeaterTopItems != null && repeaterTopItems.Items.Count < 1)
{
if (e.Item.ItemType == ListItemType.Footer)
{
// Show the Error Label (if no data is present).
Label lblErrorMsg = e.Item.FindControl("lblErrorMsg") as Label;
if (lblErrorMsg != null)
{
lblErrorMsg.Visible = true;
}
}
}
}
1. You can check for repeater items count in row databound event
2. Place a label somewhere in your repeater(footer etc.)
3. If count < 1 (find your label on footer row)
4. Populate label with "No data to display"

Categories