Есть ли способ декларативно передавать значения свойства code-behind для серверных элементов управления?
Может кто-нибудь объяснить, почему вы не можете использовать встроенные блоки кода в объявлениях управления сервером в ASP.Net?
Ниже приведен простой пример...
....
<form id="form1" runat="server">
<asp:Label ID="Label1" runat="server" Text="<%= SomeProperty %>"></asp:Label>
</form>
....
Блок кода отображается буквально на странице...
<span id="Label1"><%= SomeProperty %></span>
Мои первые мысли о том, что это связано с порядком обработки этих вещей в жизненном цикле страницы. <%=...%>
блоки, насколько я понимаю, эквивалентны Response.Write(...)
в коде позади. И поскольку серверный элемент управления фактически не отображается, как объявлено в разметке, я предполагаю, что может быть невозможно обработать блок встроенного кода до того, как произойдет это отображение.
Я был бы очень благодарен любому, кто мог бы объяснить это немного лучше.
Тем не менее, блок кода привязки данных <%#...%>
очевидно, отличается в том, как он ведет себя, но может кто-нибудь сказать мне, почему это можно встроить в элемент управления сервером...
....
<asp:Repeater id=Repeater1 runat="server">
....
<ItemTemplate>
<asp:Label ID="Label1" runat="server" Text='<%# Eval(“SomeProperty”) %>'></asp:Label>
</ItemTemplate>
....
</asp:Repeater>
....
Это отлично работает.
3 ответа
Ты в основном прав насчет <%=...%>
синтаксис. Вот пример того, что происходит под капотом:
<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>
Это анализируется и создается следующий код C# (я немного упростил его):
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 ");
}
Вот пример того, что происходит под капотом для <%#...%>
синтаксис:
<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>
Создает этот код:
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);
}
Как вы можете видеть <%=...%>
Синтаксис может использоваться вне свойств серверного элемента управления для прямой визуализации возвращаемого значения. С другой стороны <%#...%>
синтаксис генерирует обработчик события для события DataBinding метки. Это событие устанавливает значение свойства метки равным значению SomeProperty. Событие DataBinding вызывается всякий раз, когда вызывается метод DataBind, поэтому я добавил этот вызов в событие Page_Load.
Надеюсь, это поможет вам понять разницу между ними.
Вы можете создать собственный ExpressionBuilder, чтобы использовать что-то вроде <%$ Code: SomeProperty %>
Вы можете создать собственный элемент управления привязкой данных, например,
namespace FooBar.WebControls
{
public class DataBoundPlaceHolder:PlaceHolder
{
private bool hasDataBound = false;
protected override void CreateChildControls()
{
if (!hasDataBound)
{
this.DataBind();
hasDataBound = true;
}
base.CreateChildControls();
}
}
}
Затем оберните ваш код в этот новый элемент управления и используйте <%# %>
синтаксис, например
<%@ 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>