![](img/tr.png)
V tomto článku se budeme bavit o začleňování stránek do společného vzhledového systému pomocí Master Pages. Dále o skrytém poli ViewState, odkazování na jiné stránky v rámci naší webové aplikace a v neposlední řadě o dynamickém generování titulku.
Úvod
Při tvorbě webu je většinou potřeba, aby se sjednotil vzhled stránek. Pokud bychom měli například dvě stránky - o_mne.aspx a muj_blog.aspx - a potřebovali bychom u těchto stránek sjednotit vzhled. První, co by nás napadlo, by asi bylo kopírovat prvky HTML definující vzhled z jedné stránky na druhou. To by mohlo být řešení pro webovou aplikaci o maximálně 2-3 stránkách. Ovšem představte si, že takto řešíte vzhled u aplikace, kde je dohromady okolo 20-30 stránek a v průběhu programování si uvědomíte, že chcete do layoutu přidat panel s novinkami, opravdu si to užijte - 30× otevřít soubor, zkopírovat obsah na přesně uvedené místo a zavřít soubor.
Jak to řešit?
V PHP bychom něco takového nejspíše řešili funkcí include() do každé stránky, ovšem i toto řešení je mnohdy neefektivní a krkolomné. V ASP.NET pro tyto účely máme velice pěkný nástroj - Master Pages. Jednoduše si vytvoříte soubor s příponou *.master, ve které layout definujete tak, jako byste dělali normální stránku v souboru *.aspx. Jediný rozdíl bude v tom, že na místa, kde budete chtít generovat obsah, umístíte komponentu ContentPlaceHolder. Potom vytvoříte klasickou *.aspx stránku a v direktivě Page nastavíte vlastností MasterPageFile adresu k souboru s příponou *.master, kde máte definovaný vzhled. Potom obsah, který budete chtít zobrazit, umístíte do komponenty Content.
Je samozřejmě možné umístit do Master Page více komponent ContentPlaceHolder. Potom pro nás bude klíčová vlastnost ContentPlaceHolderID, díky které se budou rozlišovat dosazované obsahy. Následně musí být dvě takovéto komponenty Content samozřejmě i ve stránce *.aspx.
Master Pages, nyní prakticky
Otevřete si webovou aplikaci z minula a budeme pokračovat ve stejném projektu.
Vytvoření souboru Master Page
Nyní si vytvoříme onen kouzelný soubor MasterPage.master. Klikněte pravým tlačítkem na název projektu (v panelu Solution Explorer) a vyberte možnost Add New Item.
Vyberte samozřejmě položku Master Page. Název zanechte na MasterPage.master.
Po vytvoření souboru vidíme, že Visual Studio nám automaticky vytvořilo dva ContentPlaceHoldery. Nám ovšem bude stačit pouze jeden, takže ContentPlaceHolder, který je umístěný v hlavičce stránky, smažte. Rovnou si vytvoříme naprosto jednoduchý vzhled a výsledný kód by mohl vypadat nějak takto:
<%@ Master Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
<style type="text/css">
body { background-color: #666; font-family: Arial, Helvetica, sans-serif;}
div#page {width:400px; background-color:#ddd; border:1px dashed #222; border-radius:10px; padding:10px;}
h1 {color:#e8021b; width:400px; height:25px; font-size:23px; background-color:#fff;}
</style>
</head>
<body>
<form id="form1" runat="server">
<center>
<div id="page">
<div id="content">
<asp:ContentPlaceHolder id="ContentPlaceHolder1" runat="server">
</asp:ContentPlaceHolder>
</div>
</div>
</center>
</form>
</body>
</html>
Nyní potřebujeme vytvořit stránku *.aspx, ve které budeme definovat obsah, který se dosadí za ContentPlaceHolder v Master Page. Nejdříve smažte soubor Default.aspx a vytvoříme nový, který bude používat naši Master Page. Uděláme to úplně jednoduše. Klikněte pravým tlačítkem na soubor Master Page a vyberte možnost Add Content Page. Vidíme zde zase komponentu Content, která je ekvivalentem ke ContentPlaceHolder v souboru Master Page. Upravte tedy obsah tohoto souboru asi takto:
<%@ Page Title="" Language="C#" MasterPageFile="~/MasterPage.master" %>
<script runat="server">
void Page_Load()
{
int r = new Random().Next(1, 3);
if (r == 1)
Label1.Text = "Modrá";
else
Label1.Text = "Červená";
}
</script>
<asp:Content ID="Content1" ContentPlaceHolderID="ContentPlaceHolder1" Runat="Server">
<h1>Hlavní stránka</h1>
<asp:Label ID="Label1" runat="server" Text="Label" />
</asp:Content>
Spuštění aplikace
Když nyní aplikaci spustíte, uvidíte, že obsah, který je zadán v naší stránce Default.aspx, má takový styl, jaký jsme definovali v Master Page.
![](/galerie/2012/04/20120401141835000000_363_385.png)
To je asi vše k Master Pages. Práce s nimi je velice jednoduchá a při vytváření webové aplikace většinou tvoří základní kámen.
Odkazování na jiné stránky v rámci aplikace
Pokud bychom chtěli odkazovat na jinou stránku, která by byla v rámci naší webové aplikace, nebyl by to žádný problém. Prostě použijeme relativní adresu souboru (*.aspx) a HTML tag <a>. Já bych se ovšem rád pozastavil u odkazování na stránky, které se nachází v různých podadresářích apod. Zde nastává trochu problém, protože buď můžeme použít absolutní adresu, což je velice krkolomné, nebo relativní adresu, což většinou není problém, ale už se to zbytečně složitě vymýšlí a z každého podadresáře to vypadá jinak.
HyperLink
ASP.NET má pro hypertextové odkazy speciální komponentu HyperLink, ve které se vlastností NavigateURL určí, na kterou stránku odkazujeme. V čem tkví samotná podstata adres v ASP.NET, je myslím vidět na příkladu níže:
<asp:HyperLink ID="HyperLink1" runat="server" NavigateUrl="~/Default2.aspx">Přejít na jinou stránku</asp:HyperLink>
Jak vidíte, je zde použit zápis ~/Default2.aspx. Ten zajistí, že pokud byste přesně v tomto tvaru zadali adresu v souboru na adrese MojeSlozka/Default.aspx, fungoval by stejně dobře jako v souboru na adrese MojeSlozka/Podslozka/Default.aspx.
![](/galerie/2012/04/20120429151129000000_363_424.png)
Je to jakoby relativní adresa v celém našem projektu. Do stránky se potom samozřejmě generuje klasická adresa bez značek ~ .
Titulek stránky
Nyní, když náš web používá Master Page, je třeba nějak zařídit zpracování titulku stránky. Tak třeba <title> použít nemůžeme, a to z jednoho prostého důvodu - tento tag lze totiž umístit pouze mezi tagy <head> a <head>. Tyto tagy tady ovšem nemáme, máme jen direktivu Page a komponentu Content.
<%@ Page Title="Hlavní stránka" Language="C#" MasterPageFile="~/MasterPage.master" %>
Bystří na to už možná přišli. Visual Studio nám totiž v direktivě Page rovnou vytvořilo vlastnost Title. Zkuste u každé stránky tuto vlastnost nastavit a potom aplikaci spustit...
Ejhle, v záložce se zobrazil text, který jste vepsali jako hodnotu vlastnosti Title!
Zpracování titulku
Nyní se pokusíme kódem před každý titulek přidat text "Můj Web |". Samozřejmě to budeme provádět ve stránce Master Page, protože budeme chtít, aby to bylo platné pro všechny stránky pod naší Master Page. Pokud chceme v Master Page (ale i v konkrétním souboru *.aspx) přistupovat ke stránce, která je právě prohlížena, používá se objekt Page. Titulek stránky potom budeme hledat pod vlastností Title. Jestliže toto víme, není problém kód sestrojit:
<script runat="server">
void Page_Load()
{
Page.Title = "Můj web | " + Page.Title;
}
</script>
Pokud tento kód vložíte do naší Master Page a aplikaci spustíte znovu, uvidíte, že titulek se upravil přesně tak, jak jsme potřebovali.
![](/galerie/2012/04/20120401222040000000_363_388.png)
Můžeme takto samozřejmě pracovat s titulkem i v konkrétní stránce (*.aspx). Například takto můžeme automaticky generovat nadpisy apod.
ViewState
Nyní se opět vrátíme trochu zpátky. Pokud si vzpomínáte, psali jsme aplikaci, kde jsme měnili text. Zkusíme vytvořit podobný příklad. Vytvoříme aplikaci, která bude reagovat na stisk tlačítka (komponenta Button), přičemž po jeho stisku necháme vypsat hlášku "klávesa stisknuta" (do komponenty Label, s kterou jsme již pracovali minule). Dále si do aplikace přidáme ještě jedno tlačítko, které nebude dělat absolutně nic (pěkné, že :-D).
Trochu vizuálního návrháře
V minulém článku jsem zmiňoval možnost použití vizuálního návrháře ve Visual Studiu. Jedná se o režim zobrazení vyvíjené stránky, kde můžeme zhruba vidět, jak bude výsledek vypadat. Toto prostředí kromě jiného také nabízí nastavení komponent jednoduchým naklikáním (ani řádka kódu), ovšem protože při takovémto postupu vytváří Visual Studio dynamicky zdrojový kód, který není vždy úplně ideální, moc se v praxi nepoužívá.
Přepněte se tedy do tohoto režimu vývoje. Vždy, když komponentu přesunete z Toolboxu do prostředí stránky, uvidíte, jak bude asi v reálném prohlížeči vypadat. Pokud budete chtít upravovat vlastnosti komponenty (toto ovšem platí i pro režim kódu, kde stačí kliknout na vybraný kus kódu s komponentou), stačí na ni kliknout a v panelu Properties se zobrazí nastavení vlastností daného objektu.
Přidejte si tedy do projektu komponentu Label a dvě komponenty Button (viz obrázek).
Nyní dvakrát poklepejte na komponentu Button1 (pozor, komponenty mají stejný textový obsah, ovšem jejich ID jsou rozdílná), čímž vytvoříte rovnou událostní proceduru onClick dané komponenty a Visual Studio vás přepne do režimu kódu. Nyní napíšeme jednoduchý CS kód, který zajistí výpis našeho textu:
<script runat="server">
protected void Button1_Click(object sender, EventArgs e)
{
Label1.Text = "Tlačítko bylo stisknuto !";
}
</script>
Mimochodem, všimněte si, že v kódu se událostní procedura kliknutí na danou komponentu zaregistrovala pomocí:
onclick="Button1_Click"
Tím jsme řekli, že na kliknutí se má provést metoda Button1_Click.
Pozor: neplést s klientskými skripty (JavaScript apod.), na ty má každá komponenta vlastnost OnClientClick.
Spuštění aplikace
Aplikaci spusťte a odzkoušejte, že se skutečně text po stisknutí tlačítka mění.
Nyní zkuste kliknout na druhé tlačítko, které nemá předem zadáno, že má něco vykonávat. Co je po stisku druhého tlačítka tak zajímavé? Právě to, že proběhl refresh stránky, ale nic se nezměnilo. Protože pokud jste skutečně nejdříve stiskli první tlačítko, tak se text v komponentě Label změnil. Když kliknete na druhé tlačítko, vykonává se nový požadavek na server, a tudíž by se měl logicky text v komponentně vrátit zpět. Co zde napovídá serveru, jaká byla hodnota v Labelu, se označuje jako ViewState. Zkuste si zobrazit zdrojový kód po kliknutí na první a potom na druhé tlačítko:
Vidíme, že zde jsou rozdílné velikosti hodnot skrytého pole _VIEWSTATE. V prvním případě je hodnota (value) jen několik málo znaků. Je to z toho důvodu, že ASP.NET zde uchovává pouze nezbytné režijní informace. Zato v druhém případě už udává informace o komponentě Label, v níž jsme měli změněn text.
Existence pole ViewState je, myslím si, tedy docela zřejmá. Uchovává informace o komponentách, událostech a dalších prvcích webové aplikace.
Pole lze samozřejmě i vypnout. Nastavuje se vlastností EnableViewState, a to buď pro celou stránku v direktivě Page, nebo pro danou komponentu stejnou vlastností. V našem případě, pokud bychom chtěli znemožnit stránce pamatovat si hodnotu v komponentě Label, nastavili bychom EnableViewState="false" pro tuto jednu komponentu:
<asp:Label ID="Label1" runat="server" Text="Label" EnableViewState="false"></asp:Label>
Jak je to s ViewState u ASP.NET WebForms 4.0?
Při používání ASP.NET WebForms se ovšem zjistilo, že většina komponent ViewState pro normální běh vlastně nepotřebuje. Takže jej lze vypnout pro celou aplikaci ve WebConfigu. Ovšem při použití vlastnosti EnableViewState nastane taková situace, že pokud ji nastavíme na False pro celou aplikaci, pro jednotlivé komponenty již nejde zapnout.
S verzí ASP.NET WebForms 4.0 přišla nová vlastnost, která toto řeší. Vlastnost má označení ViewStateMode a přijímá tyto hodnoty:
- Inherit - dědí z nadřazené komponenty (defaultní hodnota vlastnosti)
- Disabled - povoleno
- Enabled - zakázáno
Použít samozřejmě lze jak vlastnost ViewStateMode, tak EnableViewState, ovšem použití ViewStateMode je vhodnejší a praktičtější. Příklad použití metody ViewStateMode můžeme vidět níže:
<asp:Label ID="Label1" runat="server" Text="Label" ViewStateMode="Disabled"></asp:Label>
Na závěr
Toť pro tento díl vše. V dalších dílech se již budeme bavit o práci s databází v ASP.NET pomocí komponent.
Na procvičení - [1] Pomocí Master Pages a hodnoty Title stránky aspx generovat ve stránce nadpis. [2] Rozšířit příklad z minulého dílu tak, aby vygenerovaný text zobrazil v titulku stránky.