TP

Asp.Net 2 - Master pages

K čemu jsou Master pages

Velice často řešený problém při vývoji webových aplikací je, že člověk potřebuje oddělit části, které se na celém webu opakují (například hlavička a různé navigační ovládací prvky) od zbytku, který je na každý stránce jiný.

Řešeni ve verzi Asp.Net 1.1

Ve starších verzích Asp.Net je toto možné řešit pomocí ovládacích prvků (například Header, MainMenu atd..), ze kterých se jednotlvié stránky budou skládat. I tak je ale možné skládat stránky více způsoby.

Jedna cesta je vytořit pro každou stránku jeden aspx soubor a do něj vložit standardní ovládací prvky (Header a MainMenu). Zbytek stránky poté obsahuje samotné ovládací prvky, nebo nějaký statický text. Toto řešení je velmi jednoduché a umožňuje přesně to co jsme chtěli tj. oddělit základní ovládací prvky od obsahu stránek. Problém ale může nastat když je potřeba více změnit strukturu stránky (a ne vždy se to podaří udělat pouze změnou CSS stylů). Potom totiž člověk musí měnit všechny stránky, což je u větších webů docela velká práce (ikdyž bude stránka velmi dobře navržená, může tato situace nastat).

Druhou možností je vytvořit si jednu stránku (show.aspx), která obsahuje výše zmíněné standardní ovládací prvky a na místě obsahu je vložený ovládací prvek PlaceHolder. Při požadavku na stránku je stránce předán parametr, podle kterého se načte nějaký ovládací prvek (nebo i více prvků) jako obsah stránky. Toto řešení je poměrně jednoduché, ale nevýhodou je, že jednotlivé stránky mají nepěknou adresu (show.aspx?show=about). Kód na načítání ovládacích prvků je velmi jednoduchý a může vypadat přibližně takto:

// Nacita obsah stranky podle parametru v QueryString
override protected void OnInit(EventArgs e)
{
  // Podle parametru nacist jeden z ovladacich prvku..
  Control ctrl=null;
  switch(Request.QueryString["show"])
  {
    case "about":
      ctrl=LoadControl("controls/about.ascx"); break;
    default:
      ctrl=LoadControl("controls/default.ascx"); break;
  }
	
  // a ovladaci prvek se vlozi na stranku   
  pageContent.Controls.Add(ctrl);

  // Asp.Net inicializace
  InitializeComponent();
  base.OnInit(e);
}
	

Další možné řešení je vytvoření bázové stránky, která by se sama postarala o vložení základních ovládacích prvků. Od této stránky jsou potom zděděny všechny další stránky ve webu. Toto řešení sice vypadá nejčistěji, ale jeho implementace není úplně snadná záležitost a člověk musí řešit docela dost problémů. Existuje ale docela dost frameworků, které se tímto způsobem snaží přidat do Asp.Net 1.0 něco, co by se podobalo Master pages z Asp.Net 2 (pár odkazů je na konci textu).

Master pages v Asp.Net 2

Problém jednotného vzhledu je v nové verzi Asp.Net řešen pomocí master pages. Funguje to tak, že v master stránce je kód, který má být stejný na všech stránkách a ostatní stránky dodávají pouze obsah. Master stránka pomocí tagů asp:ContentPlaceHolder určí jedno, nebo více míst, kam je možné vkládat obsah a ostatní stránky pomocí asp:Content vloží do master stránku obsah (atribut ContentPlaceHolderID určuje place holder).

Jednoduchý příklad na master pages by mohl vypadat takto:

<-- Common.master -->
<%@@ Master Language="C#" %>
<html><head runat="server">
  <title>Master pages</title>
</head><body>
<form id="form1" runat="server">

  <h1>Obsah z master page</h1>
  <hr />
  <a href="prvni.aspx">Prvni stranka</a>
  <a href="druha.aspx">Druha stranka</a>
  <hr />
  
  <-- Na tomto miste se bude vkladat obsah -->
<asp:contentplaceholder id="PageContent" runat="server"> </asp:contentplaceholder> </form> </body></html>
<-- prvni.aspx -->
<%@@ Page Language="C#" Title="Titulek stranky"
    MasterPageFile="~/Common.master" %>

<-- Zde je definovan obsah stranky -->
<asp:Content ContentPlaceHolderID="PageContent" Runat="server"> Obsah stranky prijde sem... </asp:Content>

Master page je tedy obyčejná Asp.Net stránka, jenom místo direktivy Page začíná direktivou Master, má příponu master a je potomkem třídy MasterPage. Master page se volí pomocí parametru MasterPageFile v direktivě Page. Dále je zde možné zadat titulek stránky (z tohoto důvodu má master page u tagu head uvedeno runat="server"). Stránky, které používají master pages obsaují všechny ovládací prvky v prvcích asp:Content a z nich jsou ovládací prvky vkládány při renderování do master stránek.

Master page podle zařízení

Jednou z vymožeností master pages je možnost použít jinou stránku pro jiná zařízení (prohlížeče). Zařízení (prohlížeče) jsou identifikovány podle konfiguračních souborů, které naleznete v adresáři C:\­WINDOWS\­Microsoft.NET\­Framework\­v2.0.xxxxx\­CONFIG\­Browsers (narozdíl od předcházejících verzí se zde nachází pro každé zařízení jeden soubor, takže je to mnohem přehlednější a snadněji spravovatelné). Rozlišení master page podle zařízení se provede v direktivě Page takto (vím, že to tu již někdo psal, ale pro pořádek :-)):

<!-- Pro prohlizece identifikovane jako mozilla 
     pouzije jinou master page -->
<%@@ Page master="default.master"
    Mozilla:master="mozilla.master" %>

Master page podle ...

Master pages lze měnit nejen podle zařízení, ale i podle čehokoliv jiného (z kódu). Je tedy snadno možné umožnit uživateli změnu master page podle jeho preferencí. Jediné na co je třeba dát pozor je, že master page lze změnit pouze na úplném počátku dotazu na stránku (ještě dříve než začne Asp.Net cokoliv načítat). Z tohoto důvodu přibyla v Asp.Net 2 nová událost, která se vyvolává dříve než jakákoliv jiná a jmenuje se PreInit. Kód na změnu master page podle hodnoty uložené v cookie by mohl vypadat takto:

// Udalost se vyvolava pred jakymkoliv nacitanim stranky
void Page_PreInit(object sender,EventArgs e)
{
  HttpCookie ck=Request.Cookies["masterpage"];
  if (ck != null && ck.Value == "2")
  {
    // Zmenit master page na 'Master2.master'
    MasterPageFile = "Master2.master";
  }
}

Hierarchické master pages

Master pages umožňují vytvářet i hierarchickou strukturu (tedy, že jedna jedna master page (GlobalMaster.master) obsahuje nějaké hlavní rozdělení stránky a další master pages jsou odvozené od ní a dělí nějak dále její prostor pro vkládání obsahu. Toto umožňuje na větších firemních webech mít jednu hlavní master stránku, které by obsahovala např. hlavičku a základní odkazy a od ní odvozené další stránky (pro jednotlivá oddělení ve firmě), které by obsahovaly věci společné pro dané oddělení (viz obrázek).

Hierarchická struktura Master pages

Jak je to udělané

Master pages připomínají z řešení ve starších verzích nejvíce to, kde je jedna bázová stránka do které se vkládá obsah s tím rozdílem, že stránka není použita jako bázová, ale přidruží se jiným způsobem. Ve skutečnosti master pages fungují tak, že se napřed vytvoří master page (která je z odvozených stránek přístupná vlastností Master), poté se vygenerují osbsahy z asp:Content a vytvořené ovládací prvky se vloží do master page (to dělá interně metoda AddContentTemplate). Na konec se vyrenderuje master stránka. Je to tedy řešení, které není možné realizovat bez zásahů do Asp.Net a není ani možné master pages tímto způsobem zpětně přidat do starších verzí Asp.Net.

Odkazy na související stránky

Published: Monday, 3 January 2005, 12:00 AM
Author: Tomas Petricek
Typos: Send me a pull request!
Tags: