关于asp.net:有没有办法以声明方式将代码隐藏属性值传递给服务器控件?

Is there any way to declaratively pass code-behind property values to server controls?

谁能解释为什么不能在 ASP.Net 的服务器控件声明中使用内联代码块?

下面是一个简单的例子……

1
2
3
4
5
....
<form id="form1" runat="server">
   "></asp:Label>
</form>
....

代码块按字面意思呈现到页面...

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

我最初的想法是它与这些东西在页面生命周期中的处理顺序有关。据我了解, <%=...%> 块相当于代码隐藏中的 Response.Write(...) 。而且由于服务器控件实际上并未按照标记中的声明进行渲染,我想在此渲染发生之前可能无法处理嵌入式代码块。

如果有人能解释得更好一点,我将不胜感激。

但是,数据绑定代码块 <%#...%> 的行为方式明显不同,但谁能告诉我为什么可以将这些嵌入到服务器控件中...

1
2
3
4
5
6
7
8
9
....

    ....
    <ItemTemplate>
        '></asp:Label>
    </ItemTemplate>
    ....
</asp:Repeater>
....

这很好用。


您对 <%=...%> 语法的看法基本正确。
以下是幕后发生的事情的一个例子:

1
2
3
4
5
6
7
8
9
10
<script runat="server">
    public string SomeProperty { get { return"Hello World!"; } }


<form id="form1" runat="server">
    <%= SomeProperty %>
   
       "></asp:Label>
   
</form>

解析并创建以下 C# 代码(我已经简化了一点):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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("\
\
    \
\
       ");
    parameterContainer.Controls[0].RenderControl(@__w);
    @__w.Write("\
\
    \
\
   ");
}

下面是 <%#...%> 语法的底层示例:

1
2
3
4
5
6
7
8
9
10
<script runat="server">
    public string SomeProperty { get { return"Hello World!"; } }
    protected void Page_Load(object sender, EventArgs e) { Label1.DataBind(); }


<form id="form1" runat="server">
   
       "></asp:Label>
   
</form>

生成此代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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 的值。每当调用 DataBind 方法时都会触发 DataBinding 事件,这就是我将该调用添加到 Page_Load 事件的原因。
希望这将帮助您了解它们之间的区别。


你可以创建一个自定义的 ExpressionBuilder,这样你就可以使用 <%$ Code: SomeProperty %>

之类的东西


您可以创建自定义数据绑定控件,例如

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
namespace FooBar.WebControls
{
    public class DataBoundPlaceHolder:PlaceHolder
    {
        private bool hasDataBound = false;
        protected override void CreateChildControls()
        {
            if (!hasDataBound)
            {
                this.DataBind();
                hasDataBound = true;
            }
            base.CreateChildControls();
        }
    }
}

然后将您的代码package在这个新控件中,并使用 <%# %> 语法,例如

1
2
3
4
5
6
7
<%@ Register TagPrefix="WebControls" Namespace="FooBar.WebControls" Assembly="FooBar" %>

<form id="form1" runat="server">
    <WebControls:DataBoundPlaceHolder runat="server">
        '></asp:Label>
    </WebControls:DataBoundPlaceHolder>
</form>