ContentPlaceHolders: 重复内容

10

情境

我有一个使用asp.net Master Pages的应用程序,我想在页面的顶部和底部重复一些内容。目前我使用类似于以下方式:

Master Page
<html>
  <body>
    <asp:ContentPlaceHolder ID="Foo" runat="server">
    </asp:ContentPlaceHolder>
    <!-- page content -->
    <asp:ContentPlaceHolder ID="Bar" runat="server">
    </asp:ContentPlaceHolder>
  </body>
</html>
内容页
<asp:Content ID="Top" ContentPlaceHolderID="Foo" runat="server">
  <!-- content -->
</asp:Content>
<asp:Content ID="Bottom" ContentPlaceHolderID="Bar" runat="server">
  <!-- content repeated -->
</asp:Content>

维护

正如你所知,在代码中重复的东西通常不是好的。它会导致维护问题。以下是我想做的事情,但显然由于重复的id属性而无法实现:

主页面
<html>
  <body>
    <asp:ContentPlaceHolder ID="Foo" runat="server">
    </asp:ContentPlaceHolder>
    <!-- page content -->
    <asp:ContentPlaceHolder ID="Foo" runat="server">
    </asp:ContentPlaceHolder>
  </body>
</html>
内容页面
<asp:Content ID="Top" ContentPlaceHolderID="Foo" runat="server">
  <!-- content (no repetition) -->
</asp:Content>

可能吗?

是否有一种使用asp.net webforms的方法来实现这个功能?解决方案不一定要与上述内容相似,只需要达到相同的效果即可。

注释

我正在使用Visual Studio 2008中的asp.net 3.0。


1
我有一个类似的问题,但我只想在我正在维护的代码中复制标题(出于各种原因)。 - Dave
5个回答

6

如果有人仍然需要解决这个问题,以下是我的解决方案: 将其放入主页面的代码文件中。

protected override void RenderChildren(HtmlTextWriter writer)
{
    Control mainPlaceHolder = FindControl("MainContentPlaceHolder");
    Control doublePlaceHolder = FindControl("ContentDoublePlaceHolder");

    StringBuilder sb = new StringBuilder();

    using (StringWriter sw = new StringWriter(sb))
    using (HtmlTextWriter tw = new HtmlTextWriter(sw))
    {
        mainPlaceHolder.RenderControl(tw);
    }

    LiteralControl lc = new LiteralControl(sb.ToString());
    doublePlaceHolder.Controls.Add(lc);

    base.RenderChildren(writer);
}

我不确定这里是否存在性能问题,但它肯定可以工作。


5

如果您只想重复一个字符串,这对我很有用:

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

可以在其他地方引用为:

<%  Dim title As LiteralControl = TitleContent.Controls.Item(0)
    Response.Write(title.Text)
%>

没有保证这是正确的行动方针 :)

非常好的观点,戴夫。为了实现我的目标,我实际上已经尝试过这种事情。 - brad

3

正如其他人所说,根据内容本身的不同,可以采用不同的快捷方式来进行翻译。

假设您需要将“内容”作为完全功能的ASP.NET代码实现,则建议为每个ContentPage创建一个UserControl,其中包含内容本身,然后只需复制一行代码即可。

示例:

主控页面

<html>
    <body>
        <asp:ContentPlaceHolder ID="Foo" runat="server">
        </asp:ContentPlaceHolder>
        <!-- page content -->
        <asp:ContentPlaceHolder ID="Bar" runat="server">
        </asp:ContentPlaceHolder>
    </body>
</html>

内容页

<asp:Content ID="Top" ContentPlaceHolderID="Foo" runat="server">
    <uc1:Page1Control id="page1Control1" runat="server" />
</asp:Content>
<asp:Content ID="Bottom" ContentPlaceHolderID="Bar" runat="server">
    <uc1:Page1Control id="page1Control2" runat="server" />
</asp:Content>

谢谢回复。这种方法确实可行,但我认为它会比重复代码更容易出现维护问题,因为我需要在每个页面中都有一个单独的控制器文件。 - brad
1
我同意,目前我能想到的唯一方法就是通过循环控件并动态添加它们。但这会给你带来无尽的痛苦,因为事件处理程序会变得非常复杂。 - Robin Day
我认为在这些占位符中我没有使用任何事件处理程序,大部分都是静态HTML,所以这可能有效。 - brad

1

您可以为此创建一个通用用户控件,并将其添加到主页面的顶部和底部。您可以创建一个属性来描述控件是否已在顶部或底部加载。


0
根据内容,您可能可以在代码中执行此操作。 如果它只是HTML,请将其放入变量中并将其分配给其他位置。 如果有控件,您可以循环遍历控件集合并创建一个副本控件,并将其放置在其他区域。在任一情况下,第二个位置不会是ContentPlaceholder,而应该使用div。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接