为什么不能同时使用if和eval?有哪些更好的替代方案?

4
在 Asp Net 数据绑定控件中,可以使用方便的 Eval() 语法:
<div><%# Eval("MyProp") %></div>

但是不能与条件语句组合使用,对吗?

<% if (Eval("MyProp")!="") { %>
<div><%# Eval("MyProp") %></div>
<%} %>

希望能够有这个选项。

所以,我的选择是将部分标记放在CodeBehind中。我真的很喜欢将其保持在外面。还有其他可能性吗?


使用带有对象的常规内联代码效果更好<%if (mydata.MyProp!=""){%><div><%=mydata.MyProp%></div><%}%>...案子结了,我猜。 - joeriks
3个回答

7
<div runat="server" visible='<%# !String.IsNullOrEmpty(Eval("MyProp") as string) %>'>
    <%# Eval("MyProp") %>
</div>

编辑于2010年9月30日

现在我有点时间,感觉应该详细说明一下我的回答。尤其是考虑到这个问题是一个重复问题,已经有比我的原始答案更好的答案了(链接)。所以我将解决你问题的第一部分:

为什么不能结合if和eval?原因是<% ... %>代码块在页面生命周期的渲染阶段执行。ASP.NET将您的代码(此处为if语句)放入函数中,然后将该函数作为委托传递给SetRenderMethodDelegate。问题是Eval在由Page.GetDataItem返回的对象上计算表达式"MyProp"。Page.GetDataItem是一种神奇的方法,只有在调用DataBind之后才会返回一个值。到了渲染阶段时,所有数据绑定都已完成。因此在调用隐式调用Page.GetDataItem的时,将抛出以下错误:"Databinding methods [...] can only be used in the context of a databound control."。

因此,<% ... %>代码块不起作用,但是<%# ... %>代码块呢?即数据绑定表达式。数据绑定表达式确实在页面生命周期的所需部分内运行——在对DataBind的调用中。但是,这里的操作词是表达式。if语句不是表达式。将任何内容放在<%# ... %>之间都将由编译器计算为表达式。如果您将一个语句放在那里,编译器将抛出错误。

因此,我们采用了一种称为在控件的Visible属性上调用数据绑定表达式中的Eval习语。 Eval与数据绑定表达式兼容;编写表达式就足以分配属性的值;而Visible属性能够实现类似于使用内联if语句的效果。 最后一个提示:如果您发现没有任何现有控件可以自然地添加Visible条件的情况,您始终可以使用<asp:PlaceHolder>,这是一种不会向标记添加任何标签的控件。

visible="False" 可以工作,但不是很优雅的解决方案,您觉得呢? - joeriks
再想一想 - 这确实是一个不错的解决方案,它将从标记中省略整个标签。(我的第一个想法是添加style="display:none"。)谢谢! - joeriks
感谢您的回复,这正是我一直苦苦寻找的解决方案。 - montueron

1
这是因为 Eval("MyProp") 返回的是对象,你不能将对象与字符串进行比较。如果 MyProp 是字符串类型,你可能需要将它强制转换为字符串。

对我没用,而且我在Google上搜索后真的认为这是个死胡同。 - joeriks

-1
<% if ((string)Eval("MyProp") != "")
 { %>
<div>
    <%# Eval("MyProp") %></div>
<%} %>

或者

<%# (string)Eval("MyProp") != "" ? string.Format("<div>{0}</div>", Eval("MyProp")) : "" %>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接