Introduction
This article is about small problem I got stuck when I tried to use inheritance with Nested Master Pages. If you looking for something general about Master Pages please try to see this article Inside Master Pages
Problem description
Well, here is my situation
As you can see I try to inherit Child.Master from Main.Master and then use Child.Master in MyPage.
Main.master
<%@ Master Language="C#" AutoEventWireup="true"
CodeBehind="Main.master.cs" Inherits="Master.Main" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
"http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head id="mainHead" runat="server">
<title>Untitled Page</title>
</head>
<body>
<form id="mainForm" runat="server">
<asp:Literal ID="TopMessageLiteral" runat="server" />
<div id="content">
<asp:contentplaceholder id="cphMain" runat="server" />
</div>
</form>
</body>
</html>
Child.master
<%@ Master Language="C#" MasterPageFile="~/Master/Main.master" AutoEventWireup="true"
CodeBehind="Child.master.cs" Inherits="Master.Child" %>
<%@ MasterType VirtualPath="~/Master/Main.master" %>
<asp:Content ID="cntMain" ContentPlaceHolderID="cphMain" Runat="Server">
<div id="left">
<asp:contentplaceholder id="cphLeftCol" runat="server" />
</div>
<div id="right">
<asp:contentplaceholder id="cphRightCol" runat="server" />
</div>
</asp:Content>
MyPage
<%@ Page Language="C#" MasterPageFile="~/Master/Child.master" AutoEventWireup="true"
Inherits="MyPage" Title="Untitled Page" Codebehind="MyPage.aspx.cs" %>
<%@ MasterType VirtualPath="~/Master/Child.master" %>
<asp:Content ID="cntLeftCol" ContentPlaceHolderID="cphLeftCol" Runat="Server">
<p>test left</p>
</asp:Content>
<asp:Content ID="cntRightCol" ContentPlaceHolderID="cphRightCol" Runat="Server">
<p>test right</p>
</asp:Content>
Code-behinds please see below:
public partial class Main : System.Web.UI.MasterPage {
private string _topMessage;
public string TopMessage {
get { return _topMessage; }
set { _topMessage = value; }
}
protected void Page_Load(object sender, EventArgs e) {
TopMessageLiteral.Text = TopMessage;
}
}
public partial class Child : Main {
protected new void Page_Load(object sender, EventArgs e) {
}
}
public partial class MyPage: System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e) {
Master.TopMessage = "My top message";
}
}
It looks like good code but it doesn't work. My TopMessage will never be shown.
If you try to debug this code you'll see that when you instantiate TopMessage property in MyPage.Page_Load all is going well and value is successfully saved to _topMessage variable. But when it will be read from Main.Page_Load it is empty.
Frankly, I don't know why. I have some guesses only. But it seems I found solution.
Solution
The trick is to use Context.Items collection.
public partial class Main : System.Web.UI.MasterPage {
public string TopMessage {
get {
if (Context.Items["_topMessage"] != null)
return Context.Items["_topMessage"].ToString();
else
return string.Empty;
}
set {
Context.Items["_topMessage"] = value;
}
}
protected void Page_Load(object sender, EventArgs e) {
TopMessageLiteral.Text = TopMessage;
}
}
In this way TopMessage value will never be lost.
One More Solution
Suggested by Irwan Hassan technic need not Main.master <- Child.master inheritance
public partial class MyPage: System.Web.UI.Page {
protected void Page_Load(object sender, EventArgs e) {
Master.Master.TopMessage = "My top message";
}
}
History
May 09, 2007: just add a piece of code to play experiments
May 10, 2007: add one more solution