如何检查ContentPlaceHolder是否为空

本文关键字:ContentPlaceHolder 是否 检查 何检查 | 更新日期: 2023-09-27 18:28:33

如何检查ContentPlaceHolder是否绝对为空?

在ContentPlaceHolder中只有文本,没有标记和控件。

示例页面。母版:

<asp:ContentPlaceHolder runat="server" ID="Content" />

示例Test.aspx:

<asp:Content runat="server" ContentPlaceHolderID="Content">
    Custom text without controls. Content.Controls.Count is 0 and Content.HasControls is false.
</asp:Content>

我需要做的是,当占位符为空时,将默认内容放在另一个控件中。

为同一占位符尝试了两次覆盖,但在动态加载时出错。

如何检查ContentPlaceHolder是否为空

您可以实现一个方法,将内容控件呈现为字符串,然后检查字符串以查找其中是否包含任何非空白字符:

private bool HasContent(Control ctrl)
{
    var sb = new System.Text.StringBuilder();
    using (var sw = new System.IO.StringWriter(sb)) 
    {
        using(var tw = new HtmlTextWriter(sw))
        {
            ctrl.RenderControl(tw);
        }
    }
    var output = sb.ToString().Trim();
    return !String.IsNullOrEmpty(output);
}
protected void Page_PreRender(object sender, EventArgs e)
{
    var placeholder = Master.FindControl("FeaturedContent");
    var hasContent = HasContent(placeholder);
}

您需要首先在主页面上找到ContentPLaceHolder。然后,您可以将第一个控件(始终存在)强制转换为LiteralControl,并使用它的Text属性。

因此,这与内容页面的Page_Load预期的一样工作:

protected void Page_Load(object sender, EventArgs e)
{
    var cph = Page.Master.FindControl("Content") as ContentPlaceHolder;
    if (contentPlaceHolder != null)
    {
        string textualContent = ((LiteralControl) cph.Controls[0]).Text;
        if (string.IsNullOrEmpty(textualContent))
        {
            // ...
        }
    }
}

这似乎已经改变了,因为我在4.5中看到,当Content中只有文字文本,甚至只有一个空白时,HasControls确实返回true。我在我的主页上做了这样的事情:

<asp:Panel id="SidebarPanel" CssClass="Sidebar" runat="server">
    <asp:ContentPlaceHolder id="SidebarContent" runat="server" />
</asp:Panel>
Sub Page_Load(...)
    SidebarPanel.Visible = SidebarContent.HasControls
End Sub

这将在<div class="Sidebar">中呈现侧边栏内容(如果有的话),并避免在没有内容的情况下在页面上创建空的div。

我真的不想为渲染运行所有代码,也不想冒一些控件在渲染后状态可能发生变化的风险。所以我想出了另一种方法。

public static int ChildrenCount(ContentPlaceHolder placeholder)
{
    int total = 0;
    total += placeholder.Controls.OfType<Control>().Where(x => 
        (!(x is ContentPlaceHolder) && !(x is LiteralControl)) ||
        (x is LiteralControl && !string.IsNullOrWhiteSpace(((LiteralControl)x).Text))
    ).Count();
    foreach (var child in placeholder.Controls.OfType<ContentPlaceHolder>())
        total += ChildrenCount(child);
    return total;
}

对我来说,我将直接放置在Content元素中的文本将由OfType作为具有适当内容的LiteralControl返回。不仅如此,我的格式("''r''n''t")也将以同样的方式返回。我还会为后续的母版页获取ContentPlaceholder,因为它们将我网页中的插槽传递到下一个母版页或实际页面。

因此,现在的任务是获取排除这些ContentPlaceholder和作为空白的LiteralControls的控件计数。使用is运算符非常容易。我们只需要确保给定的控件不是这两种类型,然后对其进行计数,或者如果它是Literal,我们会检查内容是否都是空白。最后一步是递归地为所有子ContentPlaceholder添加相同操作的结果,以便嵌套的母版页按预期工作。

最后:

if (ChildrenCount(MyContentPlaceholder) == 0)
    MyContentPlaceholder.Controls.Add(new LiteralControl("My default content!"));

我的2美分:

如果它是一个常量内容,则必须插入AND,并且根本不会有<Content>

<asp:ContentPlaceHolder>
   <!-- Anything here will be inserted if there's no Content -->
</asp:ContentPlaceHolder>
相关文章:
  • 没有找到相关文章