Asp.net asp问题:内容占位符和代码块

Asp.net asp问题:内容占位符和代码块,asp.net,asp.net-mvc,master-pages,Asp.net,Asp.net Mvc,Master Pages,当内容占位符包含任何代码块时,它会报告控件集合为空 例如: MasterPage.aspx )但如果它包含任何控件,则无法将控件集合设置为空,因为当存在脚本标记时,文本控件不会添加到控件树中。但是,仍将添加服务器控件。因此: <asp:Content ID="Content2" ContentPlaceHolderID="Content2" Runat="Server"> <%= "Code block content." %> <asp:Gri

当内容占位符包含任何代码块时,它会报告控件集合为空

例如:

MasterPage.aspx


)但如果它包含任何
控件,则无法将控件集合设置为空,因为当存在脚本标记时,文本控件不会添加到控件树中。但是,仍将添加服务器控件。因此:

<asp:Content ID="Content2" ContentPlaceHolderID="Content2" Runat="Server">
     <%= "Code block content." %>
     <asp:GridView runat="server" ID="gvTest" />
</asp:Content>

<div>Content2: <%= Content2.Controls.Count %></div>

要使这样的代码正常工作,请使用ASP.NET 需要重写的渲染 任何 脚本代码是托管的。它是通过 在上使用SetRenderMethodElegate 容器和创建自定义 渲染方法

而不是建立控制 树文字控件,仅限ASP.NET 将服务器控件添加到控件中 当标签存在于一个 容器。处理文字 内容和脚本标记,ASP.NET 生成自定义渲染方法。 然后,此方法显式写出 任何静态HTML内容和任何脚本 使用HTML文本编写器的表达式。 生成任何脚本代码() 作为方法本身的原始代码


不幸的是,对于这个难题,我想不出任何优雅的解决方案。

正如我所承诺的,我说我会看看。对不起,我昨晚没上传,这是漫长的一天,我需要好好休息一下

因此,我检查了
ContentPlaceHolder.Controls
集合在填充方式上的差异。我注意到,当使用代码块时,它会翻转为只读。在任何其他点,它都将是空的或填充的

因此,我决定加入一个扩展方法来为我们检查它:

ContentPlaceHolderExtensions.cs 然后在母版页中选中此项:

地点,主人


评论太多了,以下是我最终得到的完整代码(改编自@Rob Cooper的答案):


这包括两个额外的检查-首先检查空文本控件(如果页面包含
很好的解释,就会出现这种情况。不过,这对MVC内容来说是一种痛苦-我不想为了让母版页可以看到内容面板被使用而将内容弄乱。必须有办法解决这个问题。感谢对上一个问题的评论-稍后从办公室回家后会查看此问题。。这一个让我很感兴趣!(+1来自我!)稍后将更新:)干杯(+1和acc)这是一个不错的选择。我做了一个调整-额外检查一个只包含空格的单个LiteralControl。打得好,我正在考虑自己添加:)谢谢!
<asp:Content ContentPlaceHolderID="Content1" runat="server">
    Plain text content.
</asp:Content>

<asp:Content ContentPlaceHolderID="Content2" runat="server">
    <%= "Code block content." %>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="Content2" Runat="Server">
     <%= "Code block content." %>
     <asp:GridView runat="server" ID="gvTest" />
</asp:Content>

<div>Content2: <%= Content2.Controls.Count %></div>
public static class ContentPlaceHolderExtensions
{
    public static bool ContainsControlsOrCodeBlock(this ContentPlaceHolder placeHolder)
    {
        if (placeHolder.Controls.Count > 0)
             return true;
        
        return placeHolder.Controls.IsReadOnly;
    }
}
<asp:ContentPlaceHolder ID="Content1" runat="server" />
<asp:ContentPlaceHolder ID="Content2" runat="server" />
<asp:ContentPlaceHolder ID="Content3" runat="server" />

<div>Content1: <%= Content1.Controls.Count %></div>
<div>Content2: <%= Content2.Controls.Count %></div>
<div>Content3: <%= Content3.Controls.Count %></div>

<div>Content1 (Ex. Meth.): <%= Content1.ContainsControlsOrCodeBlock() %></div>
<div>Content2 (Ex. Meth.): <%= Content2.ContainsControlsOrCodeBlock() %></div>
<div>Content3 (Ex. Meth.): <%= Content3.ContainsControlsOrCodeBlock() %></div>
<asp:Content ContentPlaceHolderID="Content1" runat="server">
Plain Text Content
</asp:Content>

<asp:Content ContentPlaceHolderID="Content2" runat="server">
<%= "Code block content" %>
</asp:Content>
public static bool HasContent( this ContentPlaceHolder placeHolder )
{
    if ( placeHolder.Controls.Count > 0 )
    {
        LiteralControl textBlock;
        ContentPlaceHolder subContent;

        foreach ( var ctrl in placeHolder.Controls )
            if ( (textBlock = ctrl as LiteralControl) != null )
            {   //lit ctrls will hold any blocks of text
                if ( textBlock.Text != null && textBlock.Text.Trim() != "" )
                    return true;
            }
            else if ( (subContent = ctrl as ContentPlaceHolder) != null )
            {   //sub content controls should call this recursively
                if ( subContent.HasContent() )
                    return true;
            }
            else return true;   //any other control counts as content

        //controls found, but all are empty
        return false;
    }

    //if any code blocks are used the render mode will be different and no controls will
    //be in the collection, however it will be read only
    return placeHolder.Controls.IsReadOnly;
}