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.
Related
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 read this document http://support.microsoft.com/kb/976112
where explains all the embedded code blocks available but I want to combine two of them.
I want to use base <% ... %> embedded code blocks with <%# ... %> data-binding expression
Example I want to add an "If" condition to this code:
<asp:Label ID="lblHello" runat="server" Text="<%# DataBinder.Eval(Container.DataItem, "[\"Txt\"]")%>"></asp:Label>
Regards.
The difference in the <% and <%# is mainly in when they're run (the former at render time, the latter at data binding). As such, it makes no sense to "combine" them.
What you likely want to do, is to run some additional code when data binding to do your if statement. If it's a simple expression, you can just inline it:
<%# MyProperty ? Eval("Txt") : Eval("OtherTxt") %>
If it's more complicated, then it's usually best to just call a code-behind method to do it for you:
<%# MyMethod(Eval("Txt")) %>
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>
in my asp.net mark up I have a foreach loop that iterates through a simple list. In this foreach loop I am adding a new user control and attempting to pass in the value from the loop. However, this value just wont budge and get inside that damn control! Anyone have any suggestions?
<%foreach (userInfo i in this.items)
{ %>
<uc1:ItemControl ID="ItemControl" runat="server" UserID='<%#Eval("userID") %>'/>
<%} %>
userID is a public property in the control, when it goes to set, the value is just literally : <%#Eval("userID") %>. I've tried #Bind and =Value but nothing seems to work.
Any help would be appreciated!
Looks like the perfect use case for a repeater:
<asp:Repeater runat="server" id="myRepeater">
<uc1:ItemControl ID="ItemControl" runat="server" />
</asp:Repeater>
You can databind your list (this.items) to the repeater and in the code behind, in the DataBind event set the UserID property of the ItemControl control.
The reason your approach will not work is that IDs have to be unique in a page.
Try use a Repeater control for your purpose
<% if(Eval("SaveDate") != DBNull.Value){ %>
do magic
<%} %>
gives me error: Databinding methods such as Eval(), XPath(), and Bind() can only be used in the context of a databound control.
I could write : <%# Eval("SaveDate") != DBNull.Value ? do magic
But I need to do lots of html magic in if statement.
I know I should add # in order to use Eval, but not sure about correct syntax.
One solution is to wrap the content in a runat="server" tag with a Visible value, e.g.,
<div runat="server" Visible='<%# Eval("SaveDate") != DBNull.Value %>'>
do magic
</div>
div can be any HTML tag, but <asp:Panel> and <asp:PlaceHolder> could also be used. Note that "do magic" is still databound, so it's not a perfect solution if it contains expensive code or code that could generate an error if Eval("SaveDate") == DBNull.Value.
Note that Visible="false" will omit the tag and all its contents from the generated HTML, this means that it is very different from style="display:none" or style="visible:hidden", so don't worry about that.
But, if your "do magic" is reasonably complex, another rather simple solution (a bit of a hack) is: use a Repeater (or FormView) with its DataSource set to an array of one item (visible) or no items (hidden):
<asp:Repeater runat="server" DataSource='<%# ElementIfTrue(Eval("SaveDate") != DBNull.Value) %>'
<ItemTemplate>
do magic
</ItemTemplate>
</asp:Repeater>
protected IEnumerable ElementIfTrue(bool condition)
{
if (condition)
return new object[] { Page.GetDataItem() };
else
return new object[0];
}
The actual contents of the datasource array is either empty (hidden) or the element you were already binding to. This makes sure you can still call <%# Eval(...) %> inside the ItemTemplate.
With this approach, your "do magic" is a template which will only be executed if DataSource has one or more items. Which is taken care of by ElementIfTrue. It's a bit of a mind bender, but it can save you every once in a while.
As a side note: packing your "do magic" in a user control can also keep the complexity down. You don't really need to change a thing in your HTML/ASP.NET tag mix (<%# Eval("...") %> still works even inside a user control).
I usually add a protected function returning a string to the code-behind to generate the content:
On the page:
<%# Eval("SaveDate") != DBNull.Value ? GenerateContent() : string.Empty %>
In my class:
protected string GenerateContent()
{
return "Hello, World!"
}