I have a class Car, with some atributtes Model and Year. I have a list (List<Car> carList = new List<Car>()) of some objects of the class Car, and I want to put this list into an HTML tag , but I have no idea how to do this.
I got a template that already has a <table>, that's why I'm trying to use <table> instead of <asp:GridView>.
I'm using WebForms
If you are set on using a <table> and not any of the <asp:*> controls, you can manually build your markup on the page.
First, you need to be able to access the object from your markup. By making it a protected (or public) property on the code-behind, the page can access it:
protected IList<Car> CarList { get { return carList; } }
Then in the page (which inherits from the code-behind class) you can access that property to build markup. Something like this:
<% foreach (var car in CarList) { %>
<% } %>
Inside of that loop would be your rows, outside would be your table dressing. Something like this, perhaps:
<table>
<tr>
<th>Column Heading</th>
</tr>
<% foreach (var car in CarList) { %>
<tr>
<td><%= car.SomeValue %></td>
</tr>
<% } %>
</table>
This is similar to how one may construct markup in MVC, so you can think of it like that. Though it's not common for WebForms and it's often recommended to use the framework the way it's meant to be used. In the long run, if you're set on using WebForms, it may be less work to adjust the template to work with the server-side controls than to manually build the markup. The server-side controls have the added benefit of lots of event binding and code-behind interactions.
Related
I'm trying to use an imagebutton inside a foreach loop. In order to access the path to my images, I need to pass an object to ImageUrl which contains the path to my images. I tried passing the guitar.image object but it is not displaying anything, only broken images. Please give solution on this problem. By the way, the reason why im using objects is because the path to my images is inside the database. Also i've already researched about Repeater and will use it in the future, but right now i wanted know if there is a solution without repeater.
<asp:Content ID='Content1' ContentPlaceHolderID='ContentPlaceHolder1'
Runat='Server'>
<% foreach (guitarBrand guitar in brandList) { %>
<table class="one-third">
<tr>
<th rowspan="3" class="guitarLogoHover"><a href="<%= guitar.page
%>"><asp:ImageButton ID="Image" runat="server" ImageUrl="guitar.image"
Height="300px" Width="300px" /></a></th>
</tr>
</table>
<% } %>
</asp:Content>
Make sure your string in guitar.image is a proper path, relative or absolute.
ImageURL can be
"images/image1.jpg"
or
"https://website.com/images/image1.jpg"
If you are using a relative path, keep in mind that adding a / to the front will have it start at the root of your site while having no / (like the example I gave above) will begin from your current page location.
The ImageUrl property will be translated to the src attribute. Make sure this path is a correct path to the specified file.
I'm writing a repeating payments migration tool for moving from one payment system to another. All of the users' credit card and bank information is stored on those systems, so I need users to reenter the information, as I don't have it stored in my own database.
Users can either update their information or choose to delete their recurring payment and not migrate it to the new system. My migration data object includes an enum called UpdateAction with values Delete and Update.
I'm writing a review-your-input page and have a ListView control with an item template that displays all the information. When the action is to delete, there's no other information to display, so I have:
<asp:ListView ID="lvReview" runat="server">
<ItemTemplate>
<table>
<tr>
<td colspan="2"><b><%# Eval("PaymentProfileName") %></b></td>
</tr>
<tr><td>Action</td><td><%# Eval("Action").ToString() %></td></tr>
<% if ((UpdateAction)Eval("UpdateAction") == UpdateAction.Update)
{ %>
<!-- Update item bound content here -->
<% } %>
</table>
</ItemTemplate>
</asp:ListView>
This doesn't work because you have to use <%# ... %> in order to use Eval(), in which case, you can't use the if. Is there a way to reference the data item being bound in the ascx file itself? Or must I make a bunch of literal controls and put my if in a OnItemDataBound event handler?
I think you're on the right track with the OnItemDataBound event. Put your Update item bound content in a panel that you can set it's visiblity...
UpdateAction action = DataBinder.Eval(e.Item.DataItem, "UpdateAction");
if (action == UpdateAction.Update)
{
pnlUpdateItems.Visible = true;
}
else
{
pnlUpdateItems.Visible = false;
}
I've got an ASP Repeater DataBound to a DataTable, and am trying to use a code render block <% %> to do some validation via another function in the project. Basically, if the user isn't an admin, I don't want the first column displayed.
The function is returning correctly, but it still always jumps into the if block. I've tried the same code in another repeater on another page, and it works fine. Any idea why this one is behaving strangely?
<asp:Repeater runat="server" ID="batchesRPT">
<HeaderTemplate>
<table>
<tr> <% if( myProject.myUserRole.IsUserInRole( "ADMIN" ) )
{ %>
<th>Select Batch</th> <% } %>
<th>Batch ID</th>
<th>Batch Date</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<% if( GenKFI.myUserRole.IsUserInRole( "ADMIN" ) )
{ %> <td><%#Eval( "CheckboxVAL" ) %></td> <% } %>
<td><%#Eval( "BatchID" ) %></td>
<td><%#Eval( "BatchDate" ) %></td>
</tr>
</ItemTemplate>
<FooterTemplate>
</table>
</FooterTemplate>
</asp:Repeater>
UPDATE:
In the code behind previously, the CheckboxVAL would simply be omitted in the non-admin case (so it shouldn't have been a problem, since the if would keep it from getting Eval'ed).
I found this link, and thought maybe it's just evaluating the databinding tags too early. I did some stepping through, and found it would attempt to evaluate <%#Eval( "CheckboxVAL" ) %> first, error out (since CheckboxVAL didn't exist for non-admins), and then go back and evaluate the if statements. I changed it so the non-admin DataTable also contains the CheckboxVAL column, and just leave it empty. Now it will evaluate an empty column, then go back and check the if statements, and not render the first column. So now it works.
This seems like an odd behavior. Does anyone have an explanation for why it's evaluating inside the if statement, then going back later and checking the condition?
Since it seems you've solved your issue, I'll answer about your other question.
Does anyone have an explanation for why it's evaluating inside the if statement, then going back later and checking the condition?
databinding expressions <%# %> are evaluated earlier than inline code <% %>
From MSDN on databinding expressions
Data-binding expressions are resolved when the DataBind method of a
control or of the Page class is called. For controls such as the
GridView, DetailsView, and FormView controls, data-binding expressions
are resolved automatically during the control's PreRender event and
you are not required to call the DataBind method explicitly.
From MSDN on inline code
An embedded code block is server code that executes during the page's
render phase.
I have a key in web.config as -
<add key="IsDemo" value ="true"/>
I want to show/hide markup based on above web.config entry for a non-server html tag without using code behind file (as there is no .cs file and there are no runat=server controls).
Something similar to following pseudo code:
IF ( IsDemo == "true" )
THEN
<tr>
<td id="tdDemoSection" colspan="2" align="left" valign="top">
<.....>
</td>
</tr>
ENDIF
Does anyone know that we can write such conditional logic in .aspx markup?
Please help!!!
EDIT:
Section I'm hiding or showing have some data like username and password. So, I do not want user to use Firebug or Web Developer Tools to see hidden markup. markup should not go to client side.
The syntax for something like that would be
<% if(System.Configuration.ConfigurationManager.AppSettings["IsDemo"] == "true") %>
<% { %>
<!-- Protected HTML goes here -->
<% } %>
This assumes that the page is in C#.
You can firm this code up by being more defensive around the AppSettings retrieval e.g. what happens in the case where the value is null etc.
Solution:-
<% If (ConfigurationManager.AppSettings("IsDemo").ToLower().Equals("true")) Then%>
<tr>
<.....>
</tr>
<% Else%>
<tr>
<.....>
</tr>
<% End If%>
If I understand it right, you don't want to use server-side (aspx components, with runat="server" attribute) and just want to control display of html on aspx page then try this solution.
Create a property in codebehind file (or better still in some other config helper class):
//IN C# (OR VB) file
protected string Demo{
get{
return ConfigurationManager.AppSettings["IsDemo"]=="true"?
"none":"block";
}
}
In aspx page:
<tr style="display:<%= Demo%>;">
<td>blah blah</td>
</tr>
I am loving MVC 2. The whole thing just fits the web so well.
There is one piece of functionality, however, that I am unable to coax out of the Html.DisplayFor() function:
<# Page Inherits="ViewPage<IEnumerable<Foo>>">
<% foreach(var item in Model) { %>
<%: Html.DisplayFor(item.BarBaz) %>
<% } %>
I need to be able to use the DisplayTemplate for this value. Is there a way to do this?
Actually, I figured it out. How stupid of me.
This works:
<# Page Inherits="ViewPage<IEnumerable<Foo>>">
<% foreach(var item in Model) { %>
<%: Html.DisplayFor(m => item.BarBaz) %>
<% } %>
However, this will not work correctly for Html.HiddenFor and Html.ValueFor. In particular, Html.HiddenFor(m => item.NullableDecimal) will render as <input name="NullableDecimal" value="0" /> and Html.ValueFor(m => item.NullableDecimal, "0.00##) will render as 0.00##. However, if you apply a [DisplayFormat(DataFormatString = "{0:0.00########}" to your view model, then it will suddenly work. For this reason, you're probably best off using Html.Display, Html.Hidden, and Html.Value extensions, since you're less likely to run into scenarios where things fail when someone makes a non-local change.
You can accomplish it by getting away from the foreach and using a regular for loop:
<% for (int i = 0; i < Model.Count(); i++) { %>
<%: Html.DisplayFor(p=> p.ElementAt(i).BarBaz) %>
<%} %>
Another option would be to create a PartialView that took an Foo object and only displayed the information that you wanted.
<% foreach (var item in Model)
{
Html.RenderPartial("FooBarBazLine", item);
} %>
This is an old question, but i guess that someone can get benefits from my solution:
Aspx view
<%# Page Inherits="ViewPage<IEnumerable<Foo>>" %>
<% foreach (var item in Model) { %>
<%: Html.DisplayFor(m => item) %>
<% } %>
Razor view
#model IEnumerable<Foo>
#foreach (var item in Model)
{
Html.DisplayFor(m => item)
}
Since DisplayFor accepts an implicit typed lambda, we can directly indicate the instance to display in the loop.
Finally, i'm agree with Anders E. Andersen's answer for the template usage
Html.DisplayFor can automatically iterate over collections, displaying a partial view for each element in the collection.
The first thing you need to do is create an actual model class, with the collection being a property of the class.
public class Bar
{
public IEnumerable<Foo> foo { get; set; }
}
Return this class from your controller instead of the raw collection.
Secondly you need a display template for the Foo class. Display templates are partial views that need to be placed in the folder Views/Shared/DisplayTemplates.
Edit: You can have them in your controller subfolder of Views as well if you want to limit the template to a particular controller. See this question for more information.
Here is an example in razor syntax:
#model YourNameSpace.Foo
<p>#Model.BarBaz</p>
Save it as Foo.cshtml in the DisplayTemplates folder given above.
This template is pretty simple because it is based on your example where you are only displaying a string, but if the collection elements where a class with its own properties you could create a more elaborate template.
Now in the original view, you can get rid of the loop entirely and just write
#Html.DisplayFor(m => m.foo)
Notice foo is the name of the property in your new model class that contains the old collection you looped over before.
DisplayFor will automatically know that the foo property is of type (collection of) Foo and pick up the Foo.cshtml template in the DisplayTemplates folder and show it once for each element in foo.
In Razor I am using
#Html.DisplayFor(model => item.CreatedDate)
Just be careful that a DisplayFor on a POST of a form doesnt actually create a field that can be referenced back in the controller. You would need to use an additional HiddenFor if you need to refer to fields in your submitted POST method.