ContentPlaceHolders: Repeated Content

2019-04-20 18:51发布

问题:

Scenario

I have an application using asp.net Master Pages in which I would like to repeat some content at the top and bottom of a page. Currently i use something like this:

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

Maintenance

As you know, repeating things in code is usually not good. It creates maintenance problems. The following is what I would like to do but will obviously not work because of the repeated id attribute:

Master Page
<html>
  <body>
    <asp:ContentPlaceHolder ID="Foo" runat="server">
    </asp:ContentPlaceHolder>
    <!-- page content -->
    <asp:ContentPlaceHolder ID="Foo" runat="server">
    </asp:ContentPlaceHolder>
  </body>
</html>
Content Page
<asp:Content ID="Top" ContentPlaceHolderID="Foo" runat="server">
  <!-- content (no repetition) -->
</asp:Content>

Possible?

Is there a way to do this using asp.net webforms? The solution does not necessarily have to resemble the above content, it just needs to work the same way.

Notes

I am using asp.net 3.0 in Visual Studio 2008

回答1:

As others have said, depending on the content itself there are shortcuts that can be taken depending on the type of content that will be there.

Assuming however you need the "content" to be fully functioning asp.net code then I would suggest a UserControl for each ContentPage that contains the content itself and then you only need to duplicate one line of code.

Example

Master Page

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

Content Page

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


回答2:

Hey, if someone still needs a solution for this here is what I did: Put it in the Code File of your master page

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

I'm not sure about performance issues here, but it certainly works.



回答3:

In the case where you just want to repeat a string, this worked for me:

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

Can be referenced elsewhere as:

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

No warranty on that being the right course of action though :)



回答4:

You can create a COMMON user control for the same and add it to your master page in the top & bottom. You can create a property describing whether the control has loaded at the top or bottom.



回答5:

Depending on the content you may be able to do this in code. If its just HTML just put it in a variable and assign it to the other. If you have controls, you can loop over the controls collection and create a duplicate control and place it in the other area. In either case the second location would not be a contentplaceholder a div should due.