V minulém díle jsme si ukázali, jak včlenit stránku do stránky jiné. Pořád toho ale neumíme tolik, abychom mohli napsat pořádnou aplikaci. Většina webových aplikací (pokud to nejsou jen statické prezentace) je dnes napojena na relační databázi a data z této databáze zobrazuje. Protože se jedná o pravděpodobně nejčastější úkol, který při webovém vývoji budeme provádět, ASP.NET obsahuje bohatou škálu nástrojů a komponent, které nám tento úkol zjednoduší. Ještě než začneme, doporučuji k přečtení můj článek o databázích a jazyce SQL, určitě se vám bude hodit.
Komponenty pro práci s daty
Sada komponent v ASP.NET 2.0 obsahuje 5 serverových komponent pro zobrazování dat.
První z nich je komponenta GridView. Předaná data zobrazí jako tabulku, umožňuje mimo jiné třídění, stránkování, střídání stylů jednotlivých řádků a podporuje i editaci a mazání záznamů. Druhou komponentou je DataList, který je podobný jako GridView, ale máme větší svobodu volby pro zobrazení jednotlivých záznamů (nemusí to být tabulka). I tato komponenta podporuje editaci záznamů. Třetí komponentou je Repeater, který nám dává největší svobodu ohledně výstupního kódu a vzhledu dat. Neumí však záznamy editovat, což nám ale v mnoha případech nevadí, protože editaci nepotřebujeme, anebo ji provedeme na jiné stránce.
Tyto tři komponenty sloužily k zobrazení více záznamů, máme ovšem další dvě komponenty, které zobrazují pouze jeden záznam, umožňují jej editovat a kromě toho umí i přidávat záznamy nové. Jsou jimi DetailsView a FormView. DetailsView je opět tabulka - v jednom sloupci jsou názvy polí a ve druhém najdeme samotná pole pro data. FormView nám dává opět absolutní volnost v tom, jak bude záznam vypadat a jak se bude editovat.
To jsou tedy komponenty, které data zobrazují. Kromě toho musíme mít vždy další komponentu, která se připojuje k databázi a posílá do ní změny. Touto databází totiž nemusí být jen relační SQL databáze, ale i třeba soubor XML anebo nějaký bussiness-objekt, to však není nic pro začátečníky.
Vytvoření databáze
V Microsoft SQL Server 2005 máme dvě možnosti, jak vytvořit databázi. Buď si vytvoříme soubor s příponou MDF, který umístíme do adresáře App_Data naší aplikace a řekneme, že tento soubor chceme k serveru připojit, nebo necháme SQL Server vytvořit jej automaticky ve složce Program Files a tento soubor se po startu serveru připojí sám. Některé freehostingy podporují pouze první způsob - databázi nahrajete do složky App_Data a připojíte ji k serveru. Druhý způsob funguje většinou u komerčních hostingů, abyste data mohli spravovat vzdáleně. Data na server dostanete většinou tak, že na něm spustíte příslušné SQL příkazy, které vám vytvoří tabulky a naplní je daty. Tento soubor vám obyčejně vygeneruje nějaký program, někteří preferují psát si jej ručně.
My si ukážeme první způsob - vytvoření souboru MDF a připojení se k němu. Vytvořte si tedy novou webovou aplikaci v programu Visual Web Developer, v podokně Solution Explorer kliknětě pravým tlačítkem na složku App_Data a vyberte položku Add New Item.... Objeví se okno pro výběr typu souboru, zvolte typ SQL Database.
Tlačítkem Add vytvoření potvrďte a po chvíli se nám vytvoří soubor Database.mdf. Tento soubor musí být vždy ve složce App_Data, kam se dostane jen a jen webová aplikace, ale ne již uživatel z venku (není možné si jej tedy jen tak stáhnout).
Do naší databáze budeme nejprve chtít vytvořit nějakou tabulku. Najděte si tedy podokno Database Explorer (pravděpodobně musíte v soupravě nástrojů ToolBox přepnou dole záložku, nebo musíte okno zobrazit v menu View položkou Database Explorer). Rozbalte databázový soubor, pravým tlačítkem klikněte na položku Tables a vyberte možnost Add New Table.
Ve Visual Web Developeru se otevře okno pro vytvoření struktury tabulky. Nenechte se zmást - každý sloupec ve výsledné databázové tabulce je v tomto okně jeden řádek. Chce se v tom jen trochu zorientovat. Vyplňte nyní řádky tak, jako je to na obrázku - první sloupec je název daného sloupce v tabulce, druhý je jeho datový typ. Pokud zaškrtneme třetí sloupec, do daného pole bude možné vložit prázdnou hodnotu NULL.
Sloupec IdMesto je primární klíč, takže na tento řádek klikněte pravým tlačítkem a vyberte položku Set Primary Key.
Dále se do tohoto sloupce mají dosazovat automatické hodnoty. V okně vlastností pod tabulkou sloupců najděte vlastnost Identity Specification a nastavte hodnotu Yes.
Nyní stiskněte klávesovou zkratku Ctrl+S pro uložení a napište název tabulky Mesta. Tím jsme vytvořili tabulku měst. Mohli bychom ji stejně tak vytvořit pomocí příkazu CREATE TABLE, ale chtěl jsem ukázat i druhou možnost. Vývojové prostředí stejně na pozadí příkaz CREATE TABLE vygenerovalo podle nastavených hodnot a spustilo jej na databázi, je to tedy prakticky stejné.
Naplnění databáze daty
I na tohle bychom mohli použít SQL příkazy, ale ukážeme si i postup přes návrháře. Pravým tlačítkem klikněte v podokně Database Explorer na tabulku Mesta (musíte rozbalit složku Tables) a vyberte volbu Show Table Data.
Vyplňte do tabulky data podle obrázku, první sloupec nevyplňujte, vyplní se sám! Některá města jsou skutečná, některá jsem si vymyslel, výběr je čistě náhodný.
Databázi uložte a máme hotovo. Nyní zbývá jen zobrazit data na stránce.
Vytváříme a nastavujeme GridView
Naše data bude nejjednodušší zobrazit v tabulce, k tomu se nám výborně hodí komponenta GridView. Přidejte tedy na stránku Default.aspx komponentu GridView. Přepněte se do režimu Design, budeme jej teď potřebovat. Když kliknete na komponentu GridView, objeví se vedle ní malinké políčko s šipkou (menší už asi opravdu být nemohlo). Když na něj kliknete, rozbalí se panel s nejběžnějšími úkoly této komponenty.
Rozbalte seznam Choose Data Source a vyberte volbu New Data Source.... Otevře se nám dialog pro výběr datového zdroje. Vyberte položku Database a potvrďte tlačítkem OK.
Po potvrzení se objeví druhé okno, kde musíme specifikovat databázi, ke které se chceme připojovat. K tomu se používá tzv. connection string (česky asi připojovací řetězec). Ten obsahuje údaje o tom, kde databáze je, jak se k ní mám přihlásit apod. Databáze, ke kterým jsem se již připojoval, nebo které jsou v aplikaci, se zobrazí v seznamu, stačí tedy vybrat položku Database.mdf a pokračovat dál.
Abychom nemuseli při použití databáze vypisovat celý připojovací řetězec, Visual Web Developer nám nabízí možnost uložit jej do konfiguračního souboru. Na stránkách na něj speciálním způsobem pouze "odkážeme", ale bude uložen na jednom místě. V případě, že se např. změní umístění databáze, stačí tento řetězec změnit na jednom místě a ne v každé stránce. Pojmenujte tedy přípojovací řetězec MyConnectionString a potvrďte další obrazovku. Příště se nám v seznamu dostupných databází objeví tento název a stačí jej jen použít.
Nyní máme náš ConnectionString uložen a stačí již jen zadat dotaz, který se na databázi provede a jehož výsledky se zobrazí v komponentě GridView. V následujícím okně tedy zaškrtněte hvězdičku (všechny sloupce) a pokračujte dál. Dole v okně je vidět SQL příkaz, který se nad databází spustí.
V dalším okně si můžeme otestovat, co daný příkaz vrátí, to však dělat nemusíme. Potvrďte tedy tlačítkem Finish a máme vše nastaveno. V tomto poměrně dlouhém průvodci jsme nastavili vše, co budeme potřebovat. Ještě než budeme pokračovat, podíváme se na kód, který průvodce vygeneroval.
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="False" DataKeyNames="IdMesto" DataSourceID="SqlDataSource1">
<Columns>
<asp:BoundField DataField="IdMesto" HeaderText="IdMesto" InsertVisible="False" ReadOnly="True"
SortExpression="IdMesto" />
<asp:BoundField DataField="Nazev" HeaderText="Nazev" SortExpression="Nazev" />
<asp:BoundField DataField="PocetObyvatel" HeaderText="PocetObyvatel" SortExpression="PocetObyvatel" />
<asp:CheckBoxField DataField="Okresni" HeaderText="Okresni" SortExpression="Okresni" />
<asp:BoundField DataField="Web" HeaderText="Web" SortExpression="Web" />
</Columns>
</asp:GridView>
<asp:SqlDataSource ID="SqlDataSource1" runat="server" ConnectionString="<%$ ConnectionStrings:MyConnectionString %>"
SelectCommand="SELECT * FROM [Mesta]"></asp:SqlDataSource>
Nejprve máme komponentu GridView. Má nastavenou vlastnost AutoGenerateColumns na hodnotu False, což znamená, že musíme uvést dovnitř elementu Columns všechny sloupce, které tam chceme mít. Pokud sekci Columns odstraníme a nastavíme tuto vlastnosti na True, sloupce se vygenerují samy až podle toho, co vrátí databáze. Nebudeme ale již moci ovlivnit jejich další nastavení. Průvodce nám je tedy vygeneroval již nyní, abychom nastavení měnit mohli.
Vlastnost DataKeyNames označuje název primárního klíče a je důležité zejména při editaci a mazání záznamů. Důležitou vlastností je pak DataSourceId, které obsahuje ID komponenty, která poskytuje data, a tou je SqlDataSource1.
Dále uvnitř GridView obsahuje definice sloupců - BoundField je obyčejný sloupec, který jen vypíše hodnotu z databáze, DataField je název sloupce, jehož hodnota se má vypsat, HeaderText je text zobrazený v záhlaví sloupce a SortExpression určuje název sloupce, podle kterého bychom třídili, pokud by bylo třídění povolené.
Druhou komponentou je SqlDataSource1, což je komponenta, která se připojuje k databázi a poskytuje data našemu GridView. Vlastnost SelectCommand obsahuje normální SQL příkaz, který získá příslušná data z databáze. O něco zajímavější je vlastnost ConnectionString. Do ní bychom měli přímo vypsat daný připojovací řetězec, ale aby nemusel být na každé stránce, použili jsme takzvaný Custom Expression, což je speciální konstrukce, která vrací hodnotu. Uvozuje se do znaků <%$ a %> a obsahuje vždy dvě hodnoty oddělené dvojtečkou. Pokud dáme před dvojtečku ConnectionStrings a za ni název daného Connection Stringu, vrátí nám tato konstrukce připojovací řetězec daného názvu. Kromě připojovacích řetězců můžeme přistupovat i do Resources (lokalizovatelná data aplikace) či do nastavení aplikace v konfiguračním souboru, ale o tom až v dalších dílech. Výhodou ASP.NET je, že si můžeme poměrně snadno napsat vlastní Custom Expressions, které nám vrátí, cokoliv budeme potřebovat.
Pokud nyní stránku spustíte klávesovou zkratkou Ctrl-F5, ukáže se vám tabulka s městy.
Podrobnější nastavení tabulky
Každý asi vidí, že tato tabulka nevypadá úplně nejlépe a bude to chtít ještě pár úprav, aby to nějak vypadalo. Jednak potřebujeme změnit názvy v záhlaví sloupců, určitě nebudeme zobrazovat ID města, protože nikoho nezajímá, webové adresy by mohly být odkazy a místo zaškrtávátek bychom mohli zobrazit obrázek velkého města městům okresním a obrázek malého města městům menším. A nakonec by to chtělo tabulku nějak rozumně obarvit, aby se střídal řádek světlejší s řádkem tmavším atd.
Smazání prvního sloupce
Přepněte se do řežimu Design, rozbalte panel s úkoly naší tabulky a klikněte na odkaz Edit Columns.... Objeví se dialog pro správu sloupců - v seznamu Selected fields klikněte na první sloupec a odstraňte jej. ID města totiž uživatele nezajímá, je to čistě jen pro nás.
Úprava záhlaví sloupců
Klikněte na sloupec Nazev a ve vlastnostech vedle mu najděte vlastnost HeaderText. Nastavte její hodnotu na Název města. Tím se změní záhlaví tabulky.
Sloupci PocetObyvatel nastavte název na Počet obyvatel, sloupci Okresni nastavte název na prázdný text a sloupci Web nastavte název na Oficiální web města.
Pokud nyní stránku uložíte a stisknutím Ctrl-F5 v prohlížeči obnovíte, je vidět, že tabulka se změnila a vypadá o něco lépe. Pořád to ale ještě není ono.
Formátování zobrazených dat ve sloupcích
Nejvíce se mi asi nelíbí sloupec s počtem obyvatel. Čísla by měla být určitě zarovnaná doprava a ve správném českém formátu - ne 17345, ale 17 345, zkrátka rozdělené na trojice kvůli zlepšení čitelnosti. K tomu slouží vlastnost DataFormatString. Ještě než ji ale nastavíme, řekneme si něco o formátování v .NET frameworku obecně.
Formátování se využívá k transformaci zápisů dat a jejich dosazení do šablony. Pokud tedy máme šablonu Hodnota {0} je číslo a dosadíme do ní hodnotu 123456, vyjde nám Hodnota 123456 je číslo. Místo {0} se nám dosadí předaná hodnota. My ji však chceme nějak zformátovat, za nulu tedy uvedeme dvojtečku a za dvojtečku popis požadovaného formátu. Přesné možnosti formátování jsou v dokumentaci (anglicky), já zde tedy uvedu pár příkladů. Formátovat můžeme čísla a datum, máme několik předdefinovaných formátů, pokud nám nevyhovují, můžeme si poskládat vlastní. Nás bude zajímat předdefinovaný číselný formát n. Ten dělá přesně to, co potřebujeme - zformátuje číslo podle národního nastavení. Za toto písmenko můžeme specifikovat počet desetinných míst, pro češtinu jsou standardně totiž 2. Tento počet musí být vždy dvojciferný, takže uvedeme n00. Tvrdit, že město má třeba 17 634,00 obyvatel je totiž přinejmenším odvážné. Šablona pro zformátování našeho čísla bude tedy {0:n00}. Formátování samotné by vydalo na celý článek, je to opravdu poměrně komplexní záležitost.
Nastavte tedy sloupci s počtem obyvatel hodnotu vlastnosti DataFormatString na hodnotu {0:n00}. Tím zajistíme, že se číslo zformátuje. Zde bych ale rád upozornil na jednu oficiálně uznanou chybu v ASP.NET - formátování nefunguje, pokud zároveň nenastavíme vlastnost HtmlEncode na hodnotu False. Tato vlastnost slouží k tomu, aby se zabránilo vypsání HTML kódu databáze (je to z bezpečnostních důvodů, pokud to potřebujeme, musíme hodnotu této vlastnosti nastavit na False), u čísel však toto nehrozí, takže ji vypnout můžeme.
A protože chceme počet obyvatel zarovnat doprava, rozbalte skupinu vlastností ItemStyle a vlastnost HorizontalAlign nastavte na hodnotu Right. Zavřete dialog, uložte a otevřete v prohlížeči. Vidíme, že počet obyvatel vypadá daleko čitelněji.
Webové adresy jako odkazy
Další věcí, která by byla na místě, je zobrazit webové adresy jako funkční odkazy. K tomu ale musíme provést jednu úpravu - sloupec BoundField toto neumí. Musíme použít jiný typ sloupce, a to HyperLinkField. Smažte tedy sloupec Oficiální web a v horním seznamu přidejte nový sloupec typu HyperLinkField.
Nastavte mu opět hodnotu vlastnosti HeaderText na hodnotu Oficiální web a hodnotu vlastnosti DataTextField na hodnotu Web (název sloupce, který se bude vypisovat).
Dále nastavte hodnotu vlastnosti DataNavigateUrlFormatString na hodnotu http://{0} (před URL adresami musí být http), to je šablona, do které ale musíme něco dosadit. To "něco" specifikujeme vlastností DataNavigateUrlFields, do ní tedy napíšeme opět název sloupce Web, jehož hodnotu chceme dosadit.
Možná si řeknete, že za takhle dlouhé názvy vlastností by se mělo střílet (ale ještě to není tak strašné, v .NETu najdete i o dost delší názvy). Věřte, že mám raději dlouhé názvy, ze kterých poznám alespoň přibližně, čeho se dočkám, než krátký název, ze kterého bych nepoznal nic. Pojmenování těchto vlastností má svoji logiku - vždy jsou to dvojice. DataTextField a DataTextFormatString nastavují vlastnost Text, DataNavigateUrlFields a DataNavigateUrlFormatString nastavují vlastnost NavigateUrl. A vždy první vlastnost obsahuje název (případně názvy) sloupců, jejichž hodnoty se mají dosazovat, zatímco druhá je šablona, která je nějak zformátuje.
Pokud tedy stránku uložíte a spustíte, budou se webové adresy chovat jako odkazy.
Obrázek místo zaškrtávátek
Abychom měli v projektu pořádek, vytvoříme si v projektu novou složku a pojmenujte ji images. Stačí kliknout pravým tlačítkem v Solution Exploreru na název projektu a vybrat New Folder. Stáhněte si a rozbalte tento archiv se dvěma obrázky a rozbalené obrázky uložte do naší složky images. Ikonky jsem dělal já a podle toho také vypadají, pokud byste našli lepší, určitě mi napište a já je vyměním, tyhle jsou opravdu strašné.
Jelikož pole Okresni v databázi je typu BIT, ASP.NET jej automaticky převede na hodnotu typu Boolean. Proto jsem obrázky pojmenoval okresni_True.gif a okresni_False.gif, budeme totiž hodnotu ze sloupce dosazovat do adresy.
V okně pro editaci sloupců smažte sloupec s okresním městem a přidejte hned na začátek nový sloupec ImageField. Jeho vlastnost DataImageUrlFields nastavte na hodnotu Okresni a jeho vlastnost DataImageUrlFormatString nastavte na hodnotu ~/images/okresni_{0}.gif. Tím dosáhneme správné adresy, všimněte si, že opět používám adresu začínající vlnovkou.
Opět stránku můžete uložit a prohlédnout si, jak vypadá.
Elegantní vzhled tabulky
Možná jste si na panelu s nejběžnějšími úkoly pro GridView všimli odkazu Auto format, který otevře malé okno, kde si můžete vybrat jeden z předdefinovaných formátů tabulky. Nechápu, proč tuto funkci zahrnuli, jediné, co udělá, je totální bordel v kódu - výsledné HTML je tabulka hemžící se inline styly, která vypadá naprosto šíleně. Bohužel, dost lidí tuto funkci používá a proto některé ASP.NET aplikace vypadají tak, jak vypadají. Je ovšem pravda, že některé formáty jsou poměrně hezké, takže se jimi můžeme inspirovat. Pokud ale můžeme, doporučil bych formátovat pomocí CSS, GridView je na to připraven.
Přepněte se tedy do režimu kódu a do sekce head přidejte tuto definici stylů (máme jen jednu stránku, ale principiálně nám samozřejmě nic nebrání umístit je do externího souboru).
<style type="text/css">
table.GridView
{
border-collapse: collapse;
}
tr.GridView0
{
background-color: #c8d8ff;
}
tr.GridView1
{
background-color: #e0e8ff;
}
table.GridView td
{
border: none;
padding: 2px 10px;
}
table.GridView th
{
background-color: #80a0ff;
color: white;
border: none;
padding: 2px 10px;
}
</style>
První definice stylu je pro samotné GridView jakožto element table. Předpokládám, že můžeme mít i jiné tabulky, na které tento styl aplikovat nechceme, proto jsem vytvořil třídu GridView. Pak následují dvě třídy pro řádek tabulky - GridView0 a GridView1. Tyto styly řádků se budou střídavě opakovat v tabulce, docílíme tím lepší orientace a čitelnosti. Jeden řádek tedy bude světlý, druhý tmavý. Dále mám styl buňky, uděláme kolem textu trošku prostor a buňky roztáhneme. A nakonec máme buňky záhlaví tabulky, které barevně odlišíme od zbytku.
Nyní již jen zbývá říci komponentě GridView, aby si nastavila třídu GridView, a jejím řádkům, aby střídaly třídy GridView0 a GridView1. Je to poměrně jednoduché.
Komponenta GridView má vlastnost CssClass, nastavte ji tedy na hodnotu GridView. Poměrně často se v ASP.NET budeme setkávat s komplexní vlastností typu Style - ta totiž obsahuje mnoho podvlastností, a proto ji vývojáři nastavili tak, aby se mohla zadat jako vnitřní značka. Dovnitř značky asp:GridView (ale ne do sekce Columns!) vložte tyto dva řádky:
<RowStyle CssClass="GridView0" />
<AlternatingRowStyle CssClass="GridView1" />
RowStyle je styl normálního řádku tabulky, nastavíme tedy CSS třídu GridView0. AlternatintgRowStyle je styl každého druhého řádku, nastavíme mu tedy CSS třídu na GridView1. A je hotovo.
Toto řešení je mnohem lepší než použití funkce AutoFormat. Ta do GridView vytvoří tyto značky také, ale pozadí, okraje, fonty atd. jim nastavuje ručně, ne přes CSS. Tím pádem se pro každý řádek a buňku vyrenderují do HTML jako inline styly, takže kód stránky je daleko větší a nepřehledný. Toto řešení je rozhodně lepší.
Když stránku uložíte a zobrazíte v prohlížeči, bude vypadat takto:
Až na moje odporné ikonky vypadá tabulka docela pěkně (ještě by prospěla změna písma, ale to pomocí CSS zvládnete velmi snadno). To je ale pro dnešek vše, v příštím díle se podíváme na témata, která nám umožní, aby všechny komponenty GridView vypadaly stejně i bez toho, abychom museli každé nastavovat tyto CSS třídy. ASP.NET je pro tuto funkcionalitu připraveno, stačí ji jen použít.