为什么在服务器控件中将<%= %>表达式用作属性值会导致编译错误?

54
这个问题是我在回答另一个问题时注意到的结果。现在我很好奇为什么<asp:TextBox runat="server" Visible="<%= true %>" />会导致编译错误,而不是像我预期的那样显示一个可见的文本框。
从我目前发现的情况来看,<%= %>表达式并没有像我一直认为的那样被转换为文字控件。相反,在页面呈现时,它被评估并直接写入HtmlTextWriter中。但显然,解析器(我不确定是否是将ASP.NET标记转换为.NET代码的部分的正确术语)甚至不尝试评估用作服务器控件属性值的<%= %>表达式,只是将其用作字符串。这就是我收到错误消息的原因:无法从其字符串表示形式'<%= true %>'为'Visible'属性创建类型为'System.Boolean'的对象
如果我放弃runat="server",并将<%= %>与常规html标记组合起来,就像这样:
<input type="button" id="Button1" visible='<%= true %>' />

然后解析器只是将块分成表达式之前和之后的部分,然后在渲染方法中将其写入HtmlTextWriter。大致就像这样:

    __w.Write("<input type=\"button\" id=\"Button1\" visible='");
    __w.Write(true);
    __w.Write("' />");

作为我注意到的最后一件事...当我使用<%# %> + Control.DataBind()时,我得到了我期望的结果。它将表达式连接到控件数据绑定时要使用的内容,但与<%= %>表达式不同,生成的代码实际上评估了<%# %>表达式的内容。解析器最终会生成以下内容:
[DebuggerNonUserCode]
private Button __BuildControldataboundButton()
{
    Button button = new Button();
    base.databoundButton = button;
    button.ApplyStyleSheetSkin(this);
    button.ID = "databoundButton";
    button.DataBinding += new EventHandler(this.__DataBindingdataboundButton);
    return button;
}

public void __DataBindingdataboundButton(object sender, EventArgs e)
{
    Button button = (Button) sender;
    Page bindingContainer = (Page) button.BindingContainer;
    button.Visible = true;
}

来自:

<asp:Button ID="databoundButton" Visible='<%# true %>' runat="server" />

请注意button.Visible = true;这一行是由<%# %>表达式得出的结果。
所以我的问题是..为什么第一个示例中的表达式只被视为字符串,而没有计算出"true"。两个其他示例的表达式有点类似,它们产生了我预期的代码。
这只是一个错误吗(我对此表示怀疑,因为它不是ASP.NET当前版本的新问题),还是有很好的理由我们不能像那样使用<%= %>
1个回答

97

这个:

<asp:Button runat="server" id="Button1" visible='<%= true %>' />

不会评估为此:

<asp:Button runat="server" id="Button1" visible='true' />

<%= %> 直接输出到响应流中,而 asp 标记不是响应流的一部分。假设 <%= %> 运算符对 asp 标记执行任何预处理是错误的。


另外,需要考虑 ASP.NET 生命周期与 <%# %> 和 <%= %> 运算符的关系。

  • <%# %> 语义上更类似于将值赋给对象。在 ASP.NET 生命周期中,<%# %> 运算符在页面将第一个字节写入响应缓冲区之前被评估。

  • <%= %> 的意思与 Response.Write 相同。我们需要首先执行所有的数据绑定和表单处理,并在 ASP.NET 生命周期的最后将 HTML 输出到响应缓冲区。


谢谢,很有道理,这符合我在Reflector中看到的。我想我希望“Response.Write”效果只是我使用它的方式的结果,而不是它被设计成这样的工作方式。 - Tom Jelen
11
我不得不读两遍才能理解这个答案的要点:直接输出到响应流中,而 asp 标记不是响应流的一部分,也就是说,<%=true%> 不会出现在 <asp:Button visible 属性中,而是出现在其他地方! - Andomar
你还必须在PageLoad方法中调用Button1.DataBind()。 - Omer
或者如果有很多控件需要数据绑定,可以调用Me.DataBind()来绑定页面上所有属于该页面的控件。 - Jessy
为什么在 WebForm/控件的生成代码中,它没有将 attribute="<%:value%>" 翻译成 control.Attributes["attribute"]=value? - axk

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