2009-08-13 8 views
9

¿Alguien puede explicar por qué no puede usar bloques de código en línea dentro de las declaraciones de control del servidor en ASP.Net?¿Hay alguna forma de pasar de forma declarativa los valores de propiedad de código subyacente a los controles del servidor?

El siguiente es un ejemplo sencillo ...

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

El bloque de código se vuelve literalmente a la página ...

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

Mis pensamientos iniciales son que tiene que ver con el orden que estas cosas se procesen en el ciclo de vida de la página. Los bloques <%=...%> son, según tengo entendido, equivalentes a Response.Write(...) en código subyacente. Y dado que el control del servidor no se representa como se declaró en el marcado, supongo que es posible que no se pueda procesar un bloque de código incrustado antes de que tenga lugar este procesamiento.

Estaría muy agradecido de que alguien pudiera explicarlo un poco mejor.

Sin embargo, el bloque de código <%#...%> enlace de datos es obviamente diferente en la forma en que se comporta, pero puede alguien decirme por qué es posible integrar estas dentro de un control de servidor ...

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

Estos trabajos multa.

+0

[Establecer propiedad visible con la etiqueta servidor <%= %> en Framework 3.5] (http://stackoverflow.com/questions/9595851/set-visible-property-with-server-tag-in-framework-3-5) –

Respuesta

7

su mayor parte derecha sobre la sintaxis <%=...%>. Este es un ejemplo de lo que ocurre bajo el capó:

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

Esto se analiza y el siguiente código de C# se crea (he simplificado un poco):

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 "); 
} 

Aquí es un ejemplo de lo que ocurre bajo el capó para la sintaxis <%#...%>:

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

genera este código:

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

    this.Label1 = @__ctrl; 
    @__ctrl.ApplyStyleSheetSkin(this); 
    @__ctrl.ID = "Label1"; 
    @__ctrl.DataBinding += new System.EventHandler([email protected]__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); 
} 

Como puede ver, la sintaxis <%=...%> se puede usar fuera de las propiedades de un control de servidor para representar directamente el valor devuelto. Por otro lado, la sintaxis <%#...%> genera un controlador de eventos para el evento DataBinding de la etiqueta. Este evento establece el valor de la propiedad de la etiqueta en el valor de SomeProperty. El evento DataBinding se activa siempre que se llama al método DataBind y por eso agregué esa llamada al evento Page_Load.
Espero que esto te ayude a entender la diferencia entre ellos.

+0

explicación sólida. – Merritt

3

Se puede crear una costumbre ExpressionBuilder por lo que usar algo como <%$ Code: SomeProperty %>

+0

Interesante - gracias por la respuesta. Entonces, la parte a la derecha del colon es una expresión que el ExpressionBuilder debería evaluar. Por lo tanto, ¿tendría que usar la reflexión para leer la propiedad del objeto de la página? No veo cómo funcionaría dado que el ExpressionBuilder no tendría una referencia a la página. ¿Me estoy perdiendo de algo? –

+1

El método más interesante de ExpressionBuilder es GetCodeExpression, para el que simplemente necesitaría devolver un CodeSnippetExpression del bit a la derecha de los dos puntos (que puede obtener de entry.Expression.Trim()) –

+0

Ah, y si encuentra esto respuesta interesante/útil, al menos dame un voto;) –

0

Puede crear un control de datos personalizado, p. Ej.

namespace FooBar.WebControls 
{ 
    public class DataBoundPlaceHolder:PlaceHolder 
    { 
     private bool hasDataBound = false; 
     protected override void CreateChildControls() 
     { 
      if (!hasDataBound) 
      { 
       this.DataBind(); 
       hasDataBound = true; 
      } 
      base.CreateChildControls(); 
     } 
    } 
} 

luego envolver su código en este nuevo control y uso en la sintaxis <%# %>, por ejemplo,

<%@ Register TagPrefix="WebControls" Namespace="FooBar.WebControls" Assembly="FooBar" %> 

<form id="form1" runat="server"> 
    <WebControls:DataBoundPlaceHolder runat="server"> 
     <asp:Label ID="Label1" runat="server" Text='<%# SomeProperty %>'></asp:Label> 
    </WebControls:DataBoundPlaceHolder> 
</form> 
Cuestiones relacionadas