views:

306

answers:

2

Can anyone explain why you can’t use inline code blocks within server control declarations in ASP.Net?

The following is a simple example...

....
<form id="form1" runat="server">
    <asp:Label ID="Label1" runat="server" Text="<%= SomeProperty %>"></asp:Label>
</form>
....

The code block is rendered literally to the page...

<span id="Label1"><%= SomeProperty %></span>

My initial thoughts are it has to do with the order that these things are processed in the page life-cycle. The <%=...%> blocks are, as I understand it, equivalent to a Response.Write(...) in code-behind. And since the server control is not actually rendered as declared in the markup, I suppose it may not be possible to process an embedded code block before this rendering takes place.

I would be very grateful of anyone could explain that a little better.

However, the data binding code block <%#...%> is obviously different in the way it behaves, but can anyone tell me why it is possible to embed these within a server control...

....
<asp:Repeater id=Repeater1 runat="server">
    ....
    <ItemTemplate>
        <asp:Label ID="Label1" runat="server" Text='<%# Eval(“SomeProperty”) %>'></asp:Label>
    </ItemTemplate>
    ....
</asp:Repeater>
....

This works fine.

+2  A: 

You could create a custom ExpressionBuilder so you use something like <%$ Code: SomeProperty %>

David Kemp
Interesting - thanks for the reply. So the part to the right of the colon is an expression that the ExpressionBuilder would need to evaluate. Would I therefore have to use reflection to read the property from the page object? I can't see how that would work given that the ExpressionBuilder would not have a reference to the page. Am I missing something?
Andy McCluggage
ExpressionBuilder's most interesting method is GetCodeExpression, for which you'd simply need to return a CodeSnippetExpression of the bit to the right of the colon (which you can get from entry.Expression.Trim())
David Kemp
Oh, and if you find this reply interesting/useful, at least give me a vote ;)
David Kemp
+3  A: 

Your mostly right about the <%=...%> syntax. Here is an example of what happens under the hood:

<script runat="server">
    public string SomeProperty { get { return "Hello World!"; } }
</script>

<form id="form1" runat="server">
    <%= SomeProperty %>
    <div>
        <asp:Label ID="Label1" runat="server" Text="<%= SomeProperty %>"></asp:Label>
    </div>
</form>

This is parsed and the following C# code is created (I've simplified it a bit):

private Label @__BuildControlLabel1() 
{
    Label @__ctrl = new Label();

    this.Label1 = @__ctrl;
    @__ctrl.ApplyStyleSheetSkin(this);
    @__ctrl.ID = "Label1";
    @__ctrl.Text = "<%= SomeProperty %>";
    return @__ctrl;
}

private void @__Renderform1(HtmlTextWriter @__w, Control parameterContainer) 
{
    @__w.Write( SomeProperty );
    @__w.Write("\r\n    <div>\r\n        ");
    parameterContainer.Controls[0].RenderControl(@__w);
    @__w.Write("\r\n    </div>\r\n    ");
}

Here is an example of what happens under the hood for the <%#...%> syntax:

<script runat="server">
    public string SomeProperty { get { return "Hello World!"; } }
    protected void Page_Load(object sender, EventArgs e) { Label1.DataBind(); }
</script>

<form id="form1" runat="server">
    <div>
        <asp:Label ID="Label1" runat="server" Text="<%# SomeProperty %>"></asp:Label>
    </div>
</form>

Generates this code:

private Label @__BuildControlLabel1() 
{
    Label @__ctrl = new Label();

    this.Label1 = @__ctrl;
    @__ctrl.ApplyStyleSheetSkin(this);
    @__ctrl.ID = "Label1";
    @__ctrl.DataBinding += new System.EventHandler(this.@__DataBindingLabel1);
    return @__ctrl;
}

public void @__DataBindingLabel1(object sender, EventArgs e) 
{
    Label dataBindingExpressionBuilderTarget = ((Label)(sender));
    Page Container = ((Page)(dataBindingExpressionBuilderTarget.BindingContainer));

    dataBindingExpressionBuilderTarget.Text = System.Convert.ToString( SomeProperty , System.Globalization.CultureInfo.CurrentCulture);
}

As you can see the <%=...%> syntax can be used outside of a server control's properties to directly render the returned value. On the other hand the <%#...%> syntax generates a event handler for the DataBinding event of the label. This event sets the value of the label's property to the value of SomeProperty. The DataBinding event fires whenever the DataBind method is called which is why I added that call to the Page_Load event.
Hopefully this will help you understand the difference between them.

drs9222
Solid explanation.
Merritt