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

Posted

技术标签:

【中文标题】有没有办法以声明方式将代码隐藏属性值传递给服务器控件?【英文标题】:Is there any way to declaratively pass code-behind property values to server controls? 【发布时间】:2010-11-19 06:18:02 【问题描述】:

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

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

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

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

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

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

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

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

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

这很好用。

【问题讨论】:

Set Visible property with server tag <%= %> in Framework 3.5 【参考方案1】:

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

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

下面是 &lt;%#...%&gt; 语法的底层示例:

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

如您所见,&lt;%=...%&gt; 语法可以在服务器控件的属性之外使用,以直接呈现返回值。另一方面,&lt;%#...%&gt; 语法为标签的 DataBinding 事件生成事件处理程序。此事件将标签属性的值设置为 SomeProperty 的值。每当调用 DataBind 方法时都会触发 DataBinding 事件,这就是我将该调用添加到 Page_Load 事件的原因。 希望这将帮助您了解它们之间的区别。

【讨论】:

【参考方案2】:

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

namespace FooBar.WebControls

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

然后将您的代码包装在这个新控件中,并使用&lt;%# %&gt; 语法,例如

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

【讨论】:

【参考方案3】:

你可以创建一个自定义的ExpressionBuilder,这样你就可以使用&lt;%$ Code: SomeProperty %&gt;之类的东西

【讨论】:

有趣 - 感谢您的回复。因此,冒号右侧的部分是 ExpressionBuilder 需要计算的表达式。因此,我是否必须使用反射从页面对象中读取属性?鉴于 ExpressionBuilder 没有对页面的引用,我看不出这将如何工作。我错过了什么吗? ExpressionBuilder 最有趣的方法是 GetCodeExpression,为此您只需要返回冒号右侧位的 CodeSnippetExpression(您可以从 entry.Expression.Trim() 获取) 哦,如果你觉得这个回复有趣/有用,至少给我一票;)

以上是关于有没有办法以声明方式将代码隐藏属性值传递给服务器控件?的主要内容,如果未能解决你的问题,请参考以下文章

有没有办法将 POM 参数/属性传递给 TestNG XML 文件?

如何将父控件标记值传递给 ParameterConverter [重复]

如何正确地将页面属性传递给局部视图?

如何以编程方式隐藏UWP应用程序键盘?

将空值传递给 SVG 路径(使用 d3.js)以抑制丢失数据

以编程方式将文本字段值传递给另一个视图中的标签