Set TD at runtime (depending on Label.text) - asp.net

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.

Related

Why can not use <%=...%> in the ListView

All, Generally .If we want to output a variable in a page which defined in the code-behind class file of page . We could set the variable with public or protect visibility. and in the front page we can use it like below.
<%=VariableName%>.
But I don't know why can't use it in the ListView. Please help to review my code.
In the front page
<div id="divIssuedListContainer" class="myIssuedList">
<asp:ListView id="listShower" runat="server">
<LayoutTemplate>
<div id="divIssuedListHeadTitle">
<div id="divIssuedListTitleIco">
<img alt="" src="ico/IssuedCap.png" />
</div>
<div id="divIssuedListTitleName">
<span>ISSUED</span><span>TRADE NAMES</span><span>/LICENSES</span>
</div>
<div id="divIssuedListItemNumber">
<span>
<%=iListNumber%></span>
</div>
</div>
<div style="clear:both"></div>
<div id="divIssuedListBody">
<ul>
<asp:PlaceHolder runat="server" ID="itemPlaceholder"></asp:PlaceHolder>
</ul>
</div>
</LayoutTemplate>
<ItemTemplate>
<li>
<table>
<tr>
<td>
<img alt="" src="" />
</td>
<td>
<div>
<span>
<%# Eval("altID") %>
-
<%# Eval("englishTradeName") %></span></div>
<div>
<span>Expired Date:<%# Eval("expDate") %></span>
</div>
</td>
</tr>
</table>
</li>
</ItemTemplate>
</asp:ListView>
In the code-behind of page
public partial class _Default : System.Web.UI.Page
{
protected int iListNumber = 0;
protected void Page_Load(object sender, EventArgs e)
{
List<SimpleCapModel> DataSourceList = TestDataHelper.GetMyIssuedList();
listShower.DataSource = DataSourceList;
iListNumber = DataSourceList.Count();
listShower.DataBind();
}
}
I got an error page said :
The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.Web.HttpException: The Controls collection cannot be modified because the control contains code blocks (i.e. <% ... %>).
Source Error:
Line 19: listShower.DataSource = DataSourceList;
Line 20: iListNumber = DataSourceList.Count();
Line 21: listShower.DataBind();//this line cause error.
Line 22: }
Line 23: }
And If I use the expression <%#iListNumber%>. The error is gone, but I got a empty value instead of the number of the list. please review below rendered result html :
<div id="divIssuedListItemNumber">
<span> </span>
</div>
I didn't know whether I missed something ? If I did .Please help to let me know it.thanks.
You need to use <%#iListNumber %> because you are using data-binding the ListView, otherwise you'll get the exception (see: http://support.microsoft.com/kb/976112 for more on inline expressions).
Try using <%#iListNumber.ToString %> and see if that makes a difference.
UPDATE:
The problem appears to be that your inline-expression is in the LayoutTemplate, where data-binding [apparently] won't work without either handling the OnLayoutCreated event, or extending the ListView.
See either of the following for examples of how to extend the ListView:
http://www.codeproject.com/Articles/42962/Databind-Expression-in-ListView-LayoutTemplate
http://forums.asp.net/p/1201992/3319344.aspx#3319344
Given the error you're receiving, it basically means this: you can't just randomly throw .NET tags in databound controls.
The solution is to, instead, throw that random text in a .NET control, like this: <asp:Literal Runat="server" Text="<%# iListNumber %>" />
When you put a .NET codeblock in code, it dynamically has to build a control placeholder for it. It's a little tricky. But if you wrap all your custom tags up in a control, then just that one property gets databound and the databound block remains "clean" if that makes sense.

repeater how to avoid blank html

We currently have an application which we have a repeater
<asp:Repeater ID="rptOfficials" runat="server">
<ItemTemplate>
<tr>
<td>
<p class="officials">
<%#Eval("OffPosition") %> <%#Eval("FullName") %>
</p>
<p class="officials">
<%#Eval("Phone") %>
</p>
</td>
</tr>
</ItemTemplate>
</asp:Repeater>
The Phone field is not always supplied, when not there a blank paragraph tag is generated, we're thinking of changing
<p class="officials">
<%#Eval("Phone") %>
</p>
to either:
<p class="officials">
<asp:label id="lblPhone" runat="server"/>
</p>
or:
<p class="officials">
<%#GetPhone("OffId") %>
</p>
and then have either the label return the phone number with the paragraph tags wrapped around it, or have the function return it. Is there a better way to get around this?
It depends how your Binding model is composed but I suggest adding the logic in your property (Phone) on your page your (view)model (yes you can and should use ViewModels in web forms as well).
That way you keep logic outside the view.
public string Phone {
get {
return this.phone ?? string.Empty;
}
}
That way your logic stays nicely inside your view model and your view just takes care of binding it.
If you don't want to generate the -tag, you can add a boolean property to your model.
public bool DisplayPhone{
get {
return this.Phone == string.Empty;
}
}
You then need to bind it to the visible property as Halcyon mentioned. (note you need a runat="server" for this)
<p runat="server" class="officials" visible='<% #Eval("DisplayPhone") %>'>
<% #Eval("Phone") %>
</p>
I would not recommend using "display: none" since it will keep the space of the p tag. Instead, make the p tag a server tag and set its visibility to false.
<p runat="server" class="officials" visible='<% !string.IsNullOrEmpty(#Eval("Phone")) %>'>
<% #Eval("Phone") %>
</p>
Instead of using
<p class="officials">
<%#GetPhone("OffId") %>
</p>
I prefer generate <p class="officials">foo</p> inside GetPhone(), then you can return nothing when Phone is empty.
You can add small logic like the following -
<%# string.IsNullOrWhiteSpace(Eval("Phone").ToString()) ?
"" : ("<p class=\"officials\">" + Eval("Phone") + "</p>")%>
However, if you want to add more logic, I would like to suggest to use Repeater.ItemDataBound Event
try with this
<p class="officials" <%#string.IsNullOrEmpty(Eval("Phone").ToString())? "style='display:none;':''" %> >
<%#Eval("Phone") %>
</p>

ASP:DynamicControl rendering HTML rather then displaying source

I have a ASP dynamic scaffolding project in which I am customizing a details view. In my data source I have a few fields containing HTML and I would like to display the rendered HTML on the page rather then the source HTML as it is currently doing. The control looks like this.
<tr>
<td class="DDLightHeader">
<asp:Label ID="lblStatementHtml" runat="server" Text="Statement" />
</td>
<td>
<asp:DynamicControl ID="dcStatementHtml" runat="server" DataField="StatementHtml" />
</td>
</tr>
I am confused on how to proceed since the default view for this control is the Text.ascx which is apparently nothing more then a literal (the same base control I use to render the HTML on my site. I am comfortable with creating a new FieldTemplate to render the HTML, but how can I force the html to render rather then display its source view.
To resolve the above issue I had to create anew FieldTemplate
HTML.ascx
<%# Control Language="C#" CodeBehind="HTML.ascx.cs" Inherits="ProductDynamicCMS.HTML" %>
<asp:Literal runat="server" ID="Literal1" />
HTML.cs
using System;
using System.Web.DynamicData;
using System.Web.UI;
namespace ProductDynamicCMS
{
public partial class HTML : FieldTemplateUserControl
{
protected override void OnDataBinding(EventArgs e)
{
base.OnDataBinding(e);
object val = FieldValue;
if (val != null)
Literal1.Text = val.ToString();
}
public override Control DataControl
{
get
{
return Literal1;
}
}
}
}
Then applied the UIHint for this class to the field display in the details view template.
<tr>
<td class="DDLightHeader">
<asp:Label ID="lblStatementHtml" runat="server" Text="Statement" />
</td>
<td>
<asp:DynamicControl ID="dcStatementHtml" runat="server" DataField="StatementHtml" UIHint="HTML" />
</td>
</tr>
And all was well.

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.

asp.NET: How to access repeater generated elements?

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.

Resources