首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >asp问题:ContentPlaceHolder和代码块

asp问题:ContentPlaceHolder和代码块
EN

Stack Overflow用户
提问于 2009-06-08 12:40:25
回答 3查看 2.4K关注 0票数 7

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

例如:

MasterPage.aspx

代码语言:javascript
复制
<asp:ContentPlaceHolder ID="Content1" runat="server" />
<asp:ContentPlaceHolder ID="Content2" runat="server" />

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

APage.aspx

代码语言:javascript
复制
<asp:Content ContentPlaceHolderID="Content1" runat="server">
    Plain text content.
</asp:Content>

<asp:Content ContentPlaceHolderID="Content2" runat="server">
    <%= "Code block content." %>
</asp:Content>

这将产生以下情况:

纯文本内容。代码块内容。 Content1: 1 Content2: 0

为什么母版页的ContentPlaceHolder.Controls集合为空?

我想检查ContentPlaceHolder是否已填充(也请参阅这个问题),但它是否包含任何<%=块。

有谁知道怎么绕过这件事吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2009-06-09 05:48:41

正如我所承诺的,我说过我会看一看。对不起,我昨晚没上传,白天很长,需要打干草!

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

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

ContentPlaceHolderExtensions.cs

代码语言:javascript
复制
public static class ContentPlaceHolderExtensions
{
    public static bool ContainsControlsOrCodeBlock(this ContentPlaceHolder placeHolder)
    {
        if (placeHolder.Controls.Count > 0)
             return true;
        
        return placeHolder.Controls.IsReadOnly;
    }
}

然后在母版页中检查以下内容:

Site.Master

代码语言:javascript
复制
<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>

作为概念的证明,我随后添加了一个内容页面:

Index.aspx

代码语言:javascript
复制
<asp:Content ContentPlaceHolderID="Content1" runat="server">
Plain Text Content
</asp:Content>

<asp:Content ContentPlaceHolderID="Content2" runat="server">
<%= "Code block content" %>
</asp:Content>

一切如预期(我相信).

虽然它并不完美..。我不认为在这种情况下我们能得到更多的优雅。我不知道其他控件集合是如何在这些不同的场景中设置的,所以我只连接到ContentPlaceHolder控件。其他模板化控件可能工作也可能不起作用。

有什么想法?

您可以从这里下载该项目

http://code.google.com/p/robcthegeek/source/browse/#svn/trunk/stackoverflow/964724

票数 8
EN

Stack Overflow用户

发布于 2009-08-11 13:02:47

对于评论来说太多了,下面是我终于开始工作的完整代码(改编自@Rob Cooper的回答):

代码语言:javascript
复制
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;
}

这包括两个额外的检查-首先是空文本控件(如果页面包含带有空白的<asp:Content标记的话),然后检查子ContentPlaceHolder,这将发生在任何嵌套的母版页上。

票数 3
EN

Stack Overflow用户

发布于 2009-06-08 13:31:51

控件集合是空的,因为当<%= %>脚本标记存在时,文本控件不会添加到控件树中。但是,服务器控件仍将被添加。所以:

代码语言:javascript
复制
<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>

会回来

内容2: 1

Rick有一篇很棒的文章这就解释了这种行为

要使代码像这样工作,ASP.NET需要覆盖任何脚本代码所在的特定容器的呈现。它通过在容器上使用SetRenderMethodDelegate并创建一个自定义呈现方法来实现这一点. ASP.NET没有构建控件树文本控件,而是只在容器的<% %>标记出现时才将服务器控件添加到控件树中。为了处理文字内容和脚本标记,ASP.NET生成一个自定义呈现方法。然后,该方法使用HTML显式地写出任何静态TextWriter内容和任何脚本表达式。任何脚本代码(<% %>)都是作为方法本身的原始代码生成的。

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

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/964724

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档