tags:

views:

79

answers:

2
 <% 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.

A: 

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!"
}
kbrimington
what if I want to return a lot of magic :) like html blocks and so on.. should I still use a method from codebehind for that?
Stewie Griffin
A: 

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).

Ruben
I use this code in the repeater, so can't use placeholders or any ID's from code behind..
Stewie Griffin
FYI: I cant use display:none, as Google indexes text which is hidden in display none block. I can not use Visible =false, as it's a repeater and I can not use IDs.. I could hide this only by using if statement..
Stewie Griffin
You can databind to Visible, it is a property on every server-side control. Just try `<div runat="server" visible="<%# false %>">won't be there!</div>` inside your Repeater; you'll find the entire div is gone from the HTML when you call your page and view the source.
Ruben