Programming/.NET
MasterPage 의 근본적인 목적은 페이지간 공통적인 부분을 통합하는데 있습니다. 예를 들어 아래 Default.aspx 와 Content.aspx 2개의 페이지를 보면
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        메뉴 : <a href="Default.aspx">처음</a> | <a href="contact.aspx">연락처</a><br />

        기본페이지입니다.
    </div>
    </form>
</body>
</html>
▶ Default.aspx
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        메뉴 : <a href="Default.aspx">처음</a> | <a href="contact.aspx">연락처</a><br />

        이메일주소 : anchor37@cliel.com
    </div>
    </form>
</body>
</html>

▶ contact.aspx

body -> form -> div 안에서의 일부 내용만 틀리고 모든 요소가 동일함을 알 수 있습니다. 만약 페이지가 수십개라면 같은 내용을 각 페이지마다 일일이 추가하는 것은 매우 비효휼적이며 유지관리하기에도 매우 어려운 부분이 생길 것입니다.

바로 이런 경우 마스터 페이지(MasterPage)를 사용하면 간단히 제시된 문제를 해결할 수 있습니다. 마스터 페이지를 사용하려면 우선 프로젝트에서 마우스 오른쪽 버튼을 눌러 Add -> New Item 항목을 차례로 선택합니다.


Add New Item 대화상자에서 Web Forms Master Page 를 선택하고 해당 MasterPage의 이름(예제에서는 default.Master)을 설정 후 'Add' 버튼을 누르면 다음과 같은 내용의 MasterPage가 추가됩니다.
<!DOCTYPE html>

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

    </asp:ContentPlaceHolder>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">

        </asp:ContentPlaceHolder>
    </div>
    </form>
</body>
</html>
▶default.Master

MasterPage 에 있는 ContentPlaceHolder 요소에 주목해 주세요. 이 안에 웹프로젝트에 만들어지는 각 페이지의 개별적인 내용이 추가되고 공통적인 부분은 모두 이 MasterPage에 작성됩니다. 위에서 살펴본 Default.aspx와 contact.aspx 의 공통요소를 추려내 MasterPage에 작성하면 다음과 같이 될 것입니다.
<!DOCTYPE html>

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title></title>
    <script type="text/javascript" src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
    <asp:ContentPlaceHolder ID="head" runat="server">
    </asp:ContentPlaceHolder>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        메뉴 : <a href="Default.aspx">처음</a> | <a href="contact.aspx">연락처</a><br />
        <asp:ContentPlaceHolder ID="ContentPlaceHolder1" runat="server">
        </asp:ContentPlaceHolder>
    </div>
    </form>
</body>
</html>
▶ default.Master

그리고 이 후 추가될 컨텐츠페이지에서는 MsterPage가 적용되도록 해야 하는데 그렇게 하려면 페이지를 추가할때 Add New Item 대화상자에서 'Web Form with Master Page' 항목을 선택해야 합니다.


그러면 뒤이어 컨텐츠페이지에 적용할 MasterPage를 선택할 수 있는 대화상자가 출력되는데 여기에서 방금 생성한 MasterPage를 선택합니다.


그러면 이전과 달리 아주 단촐한 내용이 들어가게 되는데 컨텐츠페이지에 작성될 공통요소가 모두 MasterPage에 빠져있기 때문입니다. 더이상 Default.aspx에는 같은 내용을 집어넣을 필요가 없는 것입니다.
<%@ Page Title="" Language="C#" MasterPageFile="~/default.Master" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="test.Default" %>

<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
</asp:Content>
▶Default.aspx

이때 마스터페이지에서는 ContentPlaceHolder 컨트롤안에 들어갈 컨텐츠 페이지의 내용이 뷰 상태를 유지할 필요가 없다면 ViewStateMode 속성을 사용해 성능을 최적화 할 수 있습니다.
<asp:ContentPlaceHolder ViewStateMode="Disabled" id="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
이제 Default.aspx 페이지가 default.Master 페이지를 마스터페이지로 사용한다는 것은 상단의 Page 지시문에서 MasterPageFile 속성으로 알 수 있습니다. 조금 다르게 얘기하자면 이 속성의 값을 바꾸면 해당 페이지에서 사용하는 MasterPage를 바꿀 수 있다는 의미가됩니다. 현재 이 속성에는 위에서 추가한 default.Master 페이지가 지정되어 있습니다.

뿐만 아니라 MasterPage 지정은 Web.config 에서도 설정이 가능한데
<system.web>
  <compilation debug="true" targetFramework="4.0" />
  <pages masterPageFile="~/default.master"></pages>
</system.web>
이렇게 하면 모든 페이지에서 같은 마스터페이지를 상속받도록 할 수 있습니다. 다만 실제로 위에서 Web.config 에 MasterPage를 설정하고 모든 페이지에서 이 설정을 따르고자 한다면 이미 생성된 각 페이지와  앞으로 추가도리 컨텐츠페이지에는 Page 지시문의 MasterPageFile 속성을 제거해야 합니다.(MasterPageFile 속성에 지정된 파일과 Web.config 에 설정된 파일이 같으면 상관없지만..) 페이지에 MasterPageFile 속성이 없으면 Web.config 의 설정을 확인하여 처리하도록 하는 동작원리를 이용하는 것입니다.

Web.config 설정을 통해 MasterPage를 지정하는 경우 다음과 같이 location 요소로 해당 폴더 혹은 파일명을 지정하여 웹프로젝트 전체가 아닌 특정 폴더나 혹은 특정파일에만 설정을 적용할 수도 있습니다.
<location path="content">
  <system.web>
    <pages masterPageFile="~/default.master"></pages>
  </system.web>
</location>
이제 Default.aspx 페이지와 같은 방법으로 contact.aspx 파일도 추가합니다. 아마 이미 추가된 Default.aspx파일의 내용과 같을 것입니다.

추가된 페이지의 내용을 보면 Content 요소가 존재하는데 이 요소의 ContentPlaceHolderID 값이 이전에 추가된 MasterPage의 ContentPlaceHolder ID와 동일함을 알 수 있습니다. 즉, MasterPage의 ContentPlaceHolder 부분의 내용이 추가된 페이지의 Content 요소로 대체되어 자연스럽게 하나의 페이지로 결합되 사용자에게 보여지는 것입니다.

물론 필요하다면 MasterPage에서 ContentPlaceHolder 요소를 추가하고 이 후 만들어질 페이지에서는 같은 ID로 Content 요소를 추가하여 공통요소에 해당하는 부분을 필요한 만큼 만들 수도 있습니다.

이제 이전에 만들어진 페이지의 내용을 동일하게 다음처럼 작성합니다.
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    기본페이지입니다.
</asp:Content>
▶ Default.aspx
<asp:Content ID="Content1" ContentPlaceHolderID="head" runat="server">
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="ContentPlaceHolder1" runat="server">
    이메일주소 : anchor37@cliel.com
</asp:Content>
▶ contact.aspx

각 페이지는 head 안에서의 추가된 jquery나 body안에 div에 있는 '메뉴...' 내용은 사라지고 오로지 해당 페이지에서 제공해야만 하는 내용들만 채워져 있습니다. 나머지 필요한 부분은 모두 MasterPage에서 상속받기 때문에 각 페이지는 해당 컨텐츠페이지에서 제공해야할 내용들에만 집중할 수 있습니다.

이런한 방식을 사용하면 마스터페이지 안에 또 다른 마스터페이지를 두는 형식을 취해 필요에 따라 마스터페이지를 여러개로 중첩시킬 수도 있습니다. 조금 바꿔서 얘기하면 하나의 컨텐츠페이지가 여러 마스터페이지를 갖는것도 가능하다는 얘기가 됩니다.

하나의 컨텐츠가 여러 마스터를 가지는 경우는 상황에 따라 다른 내용을 보여줘야 하는 경우에 쓰입니다. 예를 들어 구글 크롬이나 파이어폭스와 같은 브라우저에 따라 특정 내용을 다르게 표시하고자 하는 경우 컨텐츠페이지에서는 마스터페이지를 설정할때 해당 상황에 따른 접두어를 사용하여 페이지를 지정하는 것입니다.
<%@ Page Title="" Language="C#" MasterPageFile="~/default.master" chrome:MasterPageFile="~/chrome_default.master" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
▶ 컨첸츠 페이지에서의 마스터파일지정(크롬 사용자 별도 지정)

접두어로 지정가능한 브라우저의 목록은 C:\Windows\Microsoft.NET\Framework\[.NET Framework 버전]\Config\Browsers 에서 확인할 수 있습니다.

다만 페이지 제목의 경우 MasterPage에만 <title></title> 요소가 존재하는데 컨텐츠페이지에서의 제목은 MasterPage의 제목을 상속받습니다. 만약 컨텐츠페이지에서 따로 제목을 지정하고자 한다면 해당 페이지 지시문에 있는 Title 속성을 사용하십시오.

또한 컨텐츠 페이지에서 마스터페이지의 속성등 특정 값을 가져와야 하는 경우에는 Master 속성을 사용하여 원하는 값을 가져오면 됩니다. 예를 들어 마스터페이지에 특정 Label 컨트롤이 존재하는 경우
<form id="form1" runat="server">
<div>
    <asp:Label ID="Label1" runat="server" Text="마스터 페이지 Label"></asp:Label>
    <asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
       
    </asp:ContentPlaceHolder>
</div>
</form>
컨텐츠 페이지에서 해당 Label 의 Text 값을 가져와야 한다면 Master 속성을 사용해 다음과 같이 구현하면 됩니다.
Label1.Text = (Master.FindControl("Label1") as Label).Text;
▶ 마스터페이지의 Label1 의 Text 값을 가져와 컨텐츠페이지의 Label 에 표시

참고로 마스터페이지에서 가져와야할 대상이 컨트롤이 아닌 속성과 같은 경우에는
protected void Page_Load(object sender, EventArgs e)
{
    MasterPageValue = DateTime.Now.ToString();
}

public string MasterPageValue
{
    get;
    set;
}
컨텐츠 페이지에서 MasterType 지시자를 추가하고
<%@ MasterType VirtualPath="~/default.master" %>
Master 속성을 사용해 해당 속성의 값을 그대로 가져오면 됩니다.
protected void Page_LoadComplete(object sender, EventArgs e)
{
    Label1.Text = Master.MasterPageValue;
}
이런 방식을 이용하면 단순히 마스터페이지의 속성을 가져오는 것 뿐만 아니라 컨트롤 자체를 속성을 노출하여 마스터페이지의 컨트롤을 제어할 수도 있습니다.
protected void Page_Load(object sender, EventArgs e)
{
    Label1.Text = "내용 설정";
}

public Label MasterLabel
{
    get {
        return Label1;
    }

    set {
        Label1 = value;
    }
}
▶ 마스터페이지
Master.MasterLabel.BackColor = Color.Red;
▶ 컨텐츠페이지 에서 마스터페이지 컨트롤에 대한 속성설정

다만 주의해야할 점이 있는데 위 예제의 경우 마스터페이지의 MasterPageValue 값을 가져올때 Load 이벤트가 아니라 LoadComplete 이벤트를 사용한 이유는 컨텐츠 페이지의 Load 이벤트가 마스터페이지의 Load 이벤트보다 항상 먼저 실행되므로 만약 Load 이벤트에서 MasterPageValue 값을 가져오려 한다면 아무것도 출력되지 않기 때문입니다.

마스터페이지의 Load 이벤트에서 현재 시간에 대한 내용을 MasterPageValue 속성에 설정하기 전에 컨텐츠페이지에서의 Load 이벤트가 먼저 실행되므로 Load 보다 한단계 늦은 LoadComplete를 써야하는 것입니다.

마스터페이지와 컨텐츠페이지의 이벤트 상황(순서)을 정리하면 다음과 같습니다.

 마스터 페이지 컨트롤 초기화

 컨텐츠 페이지 컨트롤 초기화

 마스터 페이지 초기화

 컨텐츠 페이지 초기화

 컨텐츠 페이지 Load

 마스터 페이지 Load

 컨텐츠 페이지 LoadComplete

 마스터 페이지 컨트롤 로드

 컨텐츠 페이지 컨트롤 로드

참고로 마스터페이지는 LoadComplete 이벤트가 존재하지 않습니다.

마스터페이지 사용시 재미있는 점중 하나는 마스터페이지는 해당 마스터페이지와 마스터페이지를 상속받은 컨텐츠페이지는 파일의 유형(인라인 혹은 숨김코드)이나 심지어 작성되는 언어(VB나 C#)가 달라도 동작하는데는 아무런 문제가 없다는 것입니다.

예를들면 MasterPage에는 C#을 사용하고 컨텐츠 페이지는 VB를 사용한다 하더라도


페이지는 정상적으로 동작됩니다.

'Programming > .NET' 카테고리의 다른 글

[ASP.NET] Label  (0) 2014.02.20
[ASP.NET] ValidationGroup  (0) 2014.02.19
[ASP.NET] MasterPage  (0) 2014.02.18
[ASP.NET] ImageMap  (0) 2014.02.17
[ASP.NET] Image  (0) 2014.02.13
[ASP.NET] 클라이언트 콜백(Client Callback)  (0) 2014.02.12
0 0