Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Accessing Grandparent Content Placeholder in Master Pages

I've been searching the web and not finding any answers (there were a couple close questions on stack overflow but they didn't seem to get answered or be identical), so I thought I'd pose one of my own. It revolves around nested master pages and a content page accessing the Content PlaceHolder of the grandparent master even if it is not re-exposed in the parent nested master. I'm wondering if this is not possible.

Core Site.Master

<html xmlns="http://www.w3.org/1999/xhtml">
    <head runat="server">

        <title>
                <asp:ContentPlaceHolder ID="TitleContent" runat="server">
                    <%= Html.GlobalModel().PageTitle %>
                </asp:ContentPlaceHolder>
            </title>

            <asp:ContentPlaceHolder ID="HeadContent" runat="server">
            <link rel="shortcut icon" 
                href="<%= ViewContext.ClientContent( "Content/Tiki.ico" ) %>" 
                type="image/x-icon"/>
        </asp:ContentPlaceHolder>
    </head>
    <body>
        <asp:ContentPlaceHolder ID="SiteContent" runat="server"/>
    </body>
</html>

Nested Site.Master (notice how TitleContent and HeadContent weren't customized, so the 'default' content from Core Site.Master should take affect)

<%@ Master Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
    Inherits="System.Web.Mvc.ViewMasterPage" %>

<asp:Content ContentPlaceHolderID="SiteContent" runat="server">
    <asp:ContentPlaceHolder ID="SiteContent" runat="server">

        <h1>Nested Header</h1>
        <asp:ContentPlaceHolder ID="NestedContent" runat="server"/>

    </asp:ContentPlaceHolder>
</asp:ContentPlaceHolder>

ContentView.aspx (referencing Nested Site.Master, the attempted TitleContent replacement will not work.)

<%@ Page Language="C#" MasterPageFile="Site.Master" %>

<asp:Content ContentPlaceHolderID="NestedContent" runat="server">
    <p>Nested content.  This will work.</p>
</asp:Content>

<asp:Content ContentPlaceHolderID="TitleContent" runat="server">
    Nested Title.  This will **not** work.
</asp:Content>
like image 793
Terry Avatar asked Sep 02 '11 16:09

Terry


People also ask

How master page and content pages are connected?

The master page establishes a layout and includes one or more ContentPlaceHolder controls for replaceable text and controls. The content page includes only the text and controls that are merged at run time with the master page's ContentPlaceHolder controls.

What is nested master page?

Master pages can be nested, with one master page referencing another as its master. Nested master pages allow you to create componentized master pages. For example, a large site might contain an overall master page that defines the look of the site.

What does a master page contain?

A master page is a defined set of formatting that is applied to the sections of your document-style report. In a template, you can specify a master page that includes a header element, a footer element, and layout properties, such as orientation and borders.

What are advantages of master page over CSS explain nested master page in detail?

The main difference between the nested master page and a content page bound to the same top-level master page is that the nested master page can include ContentPlaceHolder controls. The nested master page's ContentPlaceHolder controls define the regions where the content pages can customize the markup.


1 Answers

ContentPlaceHolderIDs can only reference their immediate parent when listed declaratively.

The easiest fix, though not the most elegant, would be to copy the ContentPlaceHolders to Nested Site.Master with the same default code. Requires some code duplication, but gets the job done.

<%@ Master Language="C#" MasterPageFile="~/Views/Shared/Site.Master" 
    Inherits="System.Web.Mvc.ViewMasterPage" %>

<asp:Content ContentPlaceHolderID="TitleContent" runat="server">
    <asp:ContentPlaceHolder ID="NestedTitleContent" runat="server">
        <%= Html.GlobalModel().PageTitle %>
    </asp:ContentPlaceHolder>
</asp:ContentPlaceHolder>

<asp:Content ContentPlaceHolderID="SiteContent" runat="server">
    <asp:ContentPlaceHolder ID="SiteContent" runat="server">
        <h1>Nested Header</h1>
        <asp:ContentPlaceHolder ID="NestedContent" runat="server"/>
    </asp:ContentPlaceHolder>
</asp:ContentPlaceHolder>

If you don't want to do that, you could replace the placeholders with custom controls that know what to show when.

Or if you need to keep it this way, you could run a bunch of code to force early rendering to an in-memory string/buffer and replace child controls with it — but that would be a ton of hassle, and it's doubtful if it would be worth the effort.

But any of those solutions depends on your situation. If you provided more context, we could provide more specific advise.

like image 92
Jon Adams Avatar answered Nov 15 '22 20:11

Jon Adams